Visualizzazione post con etichetta PIC16F877A. Mostra tutti i post
Visualizzazione post con etichetta PIC16F877A. Mostra tutti i post

lunedì 13 giugno 2016

LCD1602 su PIC DevBoard

Codice, ripreso da un produttore cinese, su come usare LCD1602 con PIC. Compilatore MapLab IDE





Schema elettrico


main.c
---------------------------------------------
#include <pic.h>          
#include "LCD1602.h"         
//---------------------------------------
unsigned char str0[]={"Luca            "};
unsigned char str1[]={"Innocenti       "};
unsigned char str2[]={"debiaonoldcomput"};
unsigned char str3[]={"ers.blogspot.com"};
//---------------------------------------

void main(void)           
{

    LCD1602_GPIO_Init();
    LCD1602_init();      
  

    while(1)              
    {
    DisplayListChar(0,0,str0);   
    DisplayListChar(0,1,str1);
  
    Delay1602_MS(500);
 
    DisplayListChar(0,0,str2);   
    DisplayListChar(0,1,str3);
    Delay1602_MS(500);
    }
}

---------------------------------------------


 LCD1602.H
---------------------------------------------
#ifndef  __LCD1602_H
#define  __LCD1602_H


#define E   RA3           
#define RW  RA2        
#define RS  RA5         
#define busy RD7         
#define busy_init TRISD7  
#define Lcd_Date PORTD    


void Delay1602_US(unsigned int t);
void Delay1602_MS(unsigned int t);
void LCD1602_BusyTest(void);
void LCD1602_Write_Instruction(unsigned char combuf);
void LCD1602_Write_data_busy(unsigned char databuf);
void LCD1602_init(void);
void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData);
void DisplayListChar(unsigned char X,unsigned char Y,unsigned char *DData);
void LCD1602_GPIO_Init(void);


#endif

---------------------------------------------


 1602.c
---------------------------------------------
#include <pic.h>        
#include "LCD1602.h"   
__CONFIG(HS&WDTDIS&LVPDIS);




void Delay1602_US(unsigned int t)
{
     unsigned int k;     
     for(k=0;k<t;k++);   
}

void Delay1602_MS(unsigned int t)
{
     while(t--)
     Delay1602_US(200);
}
void LCD1602_BusyTest(void)
{
     busy_init=1;          
     RS=0;               
     RW=1;              
     E=1;                
     asm("NOP");         
     asm("NOP");         
     while(busy==1);      
     E=0;                
     busy_init=0;         
}


void LCD1602_Write_Instruction(unsigned char combuf)
{
     LCD1602_BusyTest();         
     RS=0;              
     RW=0;               
     E=0; 
     asm("NOP");         
     Lcd_Date=combuf;      
     asm("NOP");         
     asm("NOP");         
     E=1;              
     asm("NOP");         
     E=0;                
}


void LCD1602_Write_data_busy(unsigned char databuf)
{
     LCD1602_BusyTest();  
     RS=1;              
     RW=0;               
      E=0; 
     asm("NOP");         
     Lcd_Date=databuf;       
     asm("NOP");         
     asm("NOP");         
     E=1;                
     asm("NOP");        
     E=0;                
}



void LCD1602_init(void)
{
     Delay1602_US(1500);         
     LCD1602_Write_Instruction(0x38);
     Delay1602_US(500);         
     LCD1602_Write_Instruction(0x38);
     Delay1602_US(500);          
     LCD1602_Write_Instruction(0x38); 
     LCD1602_Write_Instruction(0x38); 
     LCD1602_Write_Instruction(0x08); 
     LCD1602_Write_Instruction(0x01); 
     LCD1602_Write_Instruction(0x06); 
     LCD1602_Write_Instruction(0x0C);
}



void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData)
{
    Y&=1;
    X&=15;
    if(Y)X|=0x40;             
    X|=0x80;                  
    LCD1602_Write_Instruction(X);
    LCD1602_Write_data_busy(DData);
}

void DisplayListChar(unsigned char X,unsigned char Y,unsigned char *DData)
{
    unsigned char ListLength=0;
    Y&=0x01;
    X&=0x0f;
    while(X<16)
    {
        DisplayOneChar(X,Y,DData[ListLength]);
        ListLength++;
        X++;
    }
}


void LCD1602_GPIO_Init(void)
{
    ADCON1=0X07;
    TRISA=0B11010011;    
    TRISD=0B00000000;    
    PORTA=0B00000000;    
    PORTD=0B00000000;    
}

---------------------------------------------

giovedì 31 marzo 2016

PIC 16F877A e ATMEGA328P standalone su breadboard

Era da un po' di tempo che volevo provare ad usare un ATMEGA328P (il microcontrollore di Arduino Uno) separato dalla sua scheda. Cio' permette di rispamiare un po' di soldi (la spesa piu' importante e' il microcontrollore con flashato il bootloader) e di elettronica (regolatore di tensione, programmatore via USB)

Per rendere le cose semplici l'obbiettivo era quello di far girare lo sketch Blink (lampeggio di un led su PIN D13)

Ho scoperto quindi che la circuiteria per usare un ATMEGA ed un PIC su una breadboard sono molto simili e si riducono sostanzialmente ad alimentare il microcontrollore e fornire il clock da un quarzo con due condensatori accessori

PIC 16F877A
Il microcontrollore e' stato programmato con PicKit 3. A differenza di ATMEGA si possono impostare differenti frequenze di clock secondo le modalita' LP (Low Power, 32.768 KHz), XT (fino a 8MHz) ed HS



Il led e' stato posto sulla pin D0



ATMEGA 328P

La configurazione minimale di un ATMEGA 328P e' molto simile a quella del PIC. In pratica e' sufficiente prima programmare il chip direttamente sulla Arduino usando la normale procedura via IDE


Il pin 1 del microcontrollore deve essere orientato verso il connettore ISCP della Arduino. Il microcontrollore e' smontato dalla Arduino Uno

Poi si rimuove il chip e lo si inserisce sulla breadboard (ATTENZIONE: i pin sono estremamente delicati e facili da piegare) . Sono sufficienti  un quarzo oscillatore da 16 MHz tra i pin 9 e 10 (vedi schema successivo) e due condensatori da 22 pF a ponte tra GND ed i due piedini dell'oscillatore. Successivamente si devono connettere i pin 7 e 20 a Vcc +5V e pin 8 e 22 a GND




Fatto cio' si puo' inserire un led sul pin 19 (che corrisponde alla porta digitale 13 nel linguaggio Arduino) per vedere se tutto funziona (ho omesso per semplicita' la resistenza sul led perche' la prova e' durata pochi secondi e non c'era il rischio di fare danni all'elettronica)










E' possibile far funzionare l'ATMEGA 328P anche con il suo clock interno a 8 MHz (senza quindi necessita' di nient'altro che l'alimentazione) ma cio' richiede di modificare il bootloader

venerdì 25 marzo 2016

Display 7 Led su Pic Dev Board

Lo schema elettrico per attivare il display a 7 Led sulla Pic Dev Board e' mostrato qui sotto




Per comandare quale posizione dei display si deve agire sulla porta A. Per esempio impostando la maschera dei bit della porta A a 0xFD si attiva il secondo posto da sinistra (maschera 11111101)  mentre con 0xDF si attiva il 6° posto da sinistra (maschera 11011111)
Impostando la porta D si decide quale carattere mostrare

Per attivare il display a 7 Led si deve spostare il jumper bianco del connettore 5x2 sulla prima posizione (VCC-SW)

Questo e' il programma
-----------------------------------
#include <xc.h>


// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

const unsigned char LED[]=
{                         
0xc0,0xf9,0xa4,0xb0,//0~3
0x99,0x92,0x82,0xf8,//4~7
0x80,0x90,0x88,0x83,//8~b
0xc6,0xa1,0x86,0x8e //c~f
};

void delay(unsigned int count);

void main(void)            
{
  unsigned int i;
  
    TRISA&=0XFD;        
TRISD=0B00000000; 
    PORTD=0xFF;       
    PORTA=0XFD;       

    while(1)        
    {
    for(i=0;i<16;i++)
      {
       PORTD=LED[i];
       delay(30);
      }
    }
}

void delay(unsigned int count)
{
unsigned int a,i;
for(i=0;i<count;i++)
{
for(a=0;a<5000;a++)
 asm("NOP");  
}
}

-----------------------------------









Programmazione PIC con PicKit3 e MPLAB Ide

Ho iniziato ad interessarmi ai PIC nel lontano 2004 quando mi sono comprato un programmatore seriale ed un paio di integrati alla Fiera dell'Elettronica di Empoli. La programmazione dei PIC non e' pero' banale rispetto alle schede Arduino per cui in seguito ho abbandonato PIC per usare le piu' intuitive Arduino con processore ATMEL...fino ad oggi.


Per programmare un PIC prima di tutto si deve acquistare un programmatore, nel mio caso un PicKit 3 comprato per una decina di euro su un e-commerce cinese

Da notare i colori della pedinatura tra il programmatore e lo zoccolo ZIF


Il programmatore viene venduto con uno zoccolo ZIF (Zero Inserction Force). Per le prove mi sono comprato dei PIC 16F877A in formato 40 pin. Per vedere l'orientazione del processore sullo zoccolo si possono leggere le istruzioni nella parte sottostante, nel mio caso il Pin 1 e' vicino alla leva di blocco dello ZIF


Per programmare i PIC si puo' usare MPLAB X Ide, scaricabile  dal sito Microchip. Attenzione che questo e' il solo ambiente di sviluppo. Per compilare i programmi dovra' essere scaricato anche il compilatore (per esempio XC8)

Creazione di un nuovo progetto in MPALB


Selezione del microcontrollore


Selezione del programmatore


Selezione del compilatore
Quando si crea un nuovo progetto un MPLAB non viene creato un file sorgente da compilare. Dopo aver creato il progetto si deve selezionare la cartella Source Files ed Add New C Main File


Per poter programmare il PIC in PICKIT 3 si deve impostare l'alimentazione dal programmatore. Questo si effettua da Run/Set Project Configuration/Customize/PicKit3/Power/Power target circuit form PicKit3





Ovviamente il primo tentativo di programmare il microprocessore e' stato quello di usare un Led. Il PIC16F877A ha 4 porte digitali (A,B,C,D) programmabili da 8 bit in input ed output



Il PIC 16F877A non e' in grado di funzionare in modo autonomo perche' necessita di un oscillatore esterno (alcuni integrati della famiglia PIC hanno invece l'oscillatore integrato). Il quarzo deve essere posto ai pin 13 e 14 con a valle dei condensatori.
Si possono usare varie combinazioni di clock (per esempio 4MHz con condensatori da 15 pF)

http://www.elektrojo.com/img/cms/fig4-29.png


Per rendere l'apprendimento un po' piu' semplice mi sono comprato una Pic Dev Board da un AliExpress. Prima nota : e' stata una pessima scelta perche' la documentazione a bordo e' tutta in cinese e organizzata in modo confuso. Sono riuscito a farla funzionare solo perche' insieme alla scheda era presente un CD con dei video tutorial (in cinese ma comunque comprensibili)



Sulla scheda sono gia' montati diversi dispositivi.
1) 8 Display a 7 Led
2) connettore per display LCD 12864
3) connettore per display LCD 1602
4) connettore per DS18B20 (termometro digitale)
5) tastiera 4x4
6) tastiera 4x1
7) 2 potenziometri collegati all'ADC del PIC
8) DS1302 (RealTime Clock) con batteria tampone
9) connettore PS2
10) RS232 connettore seriale DB9 con Max 232
11) interruttore di accesione
12) buzzer
13) 24C02 EEPROM 512 Bytes
14) HS0038 Universal IR Receiver
15) pulsante di reset per il PIC
16) resistenza variabile per gli LCD
17) 8 led verdi 

Per usare il programmatore con la Dev Board quest'ultima deve essere alimentata separatamente mediante una alimentatore a 5 V (pin + al centro) oppure dalla porta microUsb (altrimenti MPLAB IDE segnala che non c'e' abbastanza tensione, circa 4.85 V) per procedere con la programmazione)

Da notare la pedinatura di connessione tra il PICKIT3 e la Dev Board
La Dev Board ha gia' montato un quarzo da 4MHz. I led, come si vede dallo schema elettrico della Dev Board sono connessi alla porta D



Per alimentare i led si deve pero' fare un passo ulteriore. Si deve aggiungere un Jumper sul connettore 5x2 tra i pin VCC e LED VCC

Jumper bianco a fianco delle due resistenze variabili


Questo e' il programma. A differenza di Arduino si deve impostare la configurazione del processore mediante i Configuration Bits in cui si indica per esempio la sorgente dell'oscillatore ed eventuali protezioni 
Per impostare i Configuration Bits si seleziona da dentro MPLAB Window/PIC Memory Views/Configuration Bits. Si selezionano i valori desiderati e poi si clicca su Generate Source Code to Output. Si copia e si incolla quindi il risultato nel codice del sorgente


In questo programma viene acceso e spento il led connesso alla porta D0
------------------------------------
#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)


         

void delay(void);

void main(void)         
{
  TRISD=0x00;      
  PORTD=0xFF;      
  while(1)         
    {
     RD0=!RD0;     
     delay();
    }
}

void delay(void)
{
unsigned int a;    
for(a=0;a<50000;a++);   
}
------------------------------------




Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...