📄 lab4.c
字号:
/************************************************************************ *********
* Proiectarea cu Microprocesoare
* Laboratorul 4
* Folosirea convertorului analog digital. Caractere custom pe LCD
*********************************************************************************/
#include <stdio.h>
#include <avr\io.h>
#include <avr\interrupt.h>
/************************************************************************
* DEFINE-uri pentru parametrizarea modulului LCD
************************************************************************/
#define LcdDATA_DDR DDRA // Portul pe care conectam firele de date la LCD-ul
#define LcdDATA_PORT PORTA
#define LcdDATA_PIN PINA
#define LcdCMD_DDR DDRA // Portul pe care conectam firele de comenzi la LCD
#define LcdCMD_PORT PORTA
#define LcdCMD_PIN PINA
#define LcdD4 PA0 // Pin-ul pentru firul de date D4 de pe LCD
#define LcdD5 PA1 // Pin-ul pentru firul de date D5 de pe LCD
#define LcdD6 PA2 // Pin-ul pentru firul de date D6 de pe LCD
#define LcdD7 PA3 // Pin-ul pentru firul de date D7 de pe LCD
#define LcdRS PA4 // Pinul pentru selectare operatie (LCD)
#define LcdRW PA5 // Pinul pentru Read/ Write (LCD)
#define LcdE PA6 // Pinul de Enable (LCD)
#define LCD_INSTR_4wire 0x28 // 4 fire date, font 5x8
#define LCD_INSTR_display 0x0C // Display On, Cursor On, Blinking On ( 1 Display Cursor Blink )
#define LCD_INSTR_clearDisplay 0x01 // Clear Display
#define LCD_INSTR_returnHome 0x02 // Return Cursor and LCD to Home Position
#define LCD_INSTR_nextLine 0xC0 // Return Cursor and LCD to Home Position
#define LCD_INSTR_gotoCGRAM 0x40 // go to Character Generator RAM
/************************************************************************
* API LCD.. implementare este in partea de jos a fisierului
************************************************************************/
void LCD_init(); // Initializare modul LCD.. trebuie apelata inainte de a se face orice operatie cu LCD-ul
void LCD_writeInstruction(unsigned char _instruction); // Trimite o instructiune catre lcd (vezi datasheet)
void LCD_writeData(unsigned char _data); // Trimite date catre LCD pentru afisare
void LCD_write(unsigned char _byte); // trimite un bute catre LCD la modul general (nu conteaza daca e instructiune sau date)
void LCD_waitNotBusy(); // Asteptam pana cand lcd-ul devine disponibil pt o noua comanda
void LCD_waitInstructions(unsigned char _instructions); // Asteapta un numar de cicli de tact.. loop
// tine definitiile caracterelor pentru progress bar
char progress_bar[6 * 8] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , // gol
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 , // o bara verticala
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 , // doua
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C , // trei
0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E , // patru
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F // cinci
};
// initializarea convertorului analog digital
void ADC_init()
{
//TODO
// AVCC cu condesator pe AREF; PA7 ca input single ended; rezultat left-adjusted (8 biti de date)
// activeaza ADC si intreruperea de conversie. Prescaler de ceas la maximum
// pune pe input pinul intrarii de ADC (fara a modifica starea celorlalti pini)
}
// intreruperea de conversie
SIGNAL(SIG_ADC)
{
//afisare valoare tensiune scalata
}
int main()
{
int i;
LCD_init();
// initializez caracterele custom
LCD_writeInstruction(LCD_INSTR_gotoCGRAM);
for(i=0;i<6*8;i++)
LCD_writeData(progress_bar[i]);
LCD_writeInstruction(LCD_INSTR_clearDisplay);
ADC_init();
sei();
for(;;)
{
// cer ADC-ului sa faca o conversie
//TODO
}
return 0;
}
/************************************************************************
* IMPLEMENTARE API LCD.. implementare este in partea de jos a fisierului
************************************************************************/
void LCD_init()
{
LcdDATA_DDR |= (1<<LcdD4)|(1<<LcdD5)|(1<<LcdD6)|(1<<LcdD7); // setam pinii de date ca pini de iesire
LcdCMD_DDR |= (1<<LcdRS)|(1<<LcdRW)|(1<<LcdE); // setam pinii de comenzi ca pini de iesire
LCD_waitNotBusy();
LcdCMD_PORT &= ~(1<<LcdRS); // Setam linia RS pe low
LcdCMD_PORT &= ~(1<<LcdRW); // Setam linia RW pe low (acum suntem in modul de trimis instructiuni)
LcdDATA_PORT &= ~(1<<LcdD4)&~(1<<LcdD6)&~(1<<LcdD7); // Specificam ca vrem 4 fire de date, prima comanda (LcdD5 activ, restul nu)
LcdDATA_PORT |= (1<<LcdD5); // setam pinii de comenzi ca pini de iesire
LcdCMD_PORT |= (1<<LcdE); // Setam linia E(nable) pe high; aceasta ii specifica LCD-ului sa preia datele
LCD_waitInstructions(6); // Asteptam o perioada de timp T
LcdCMD_PORT &= ~(1<<LcdE ); // Setam linia E(nable) pe low; transferul s-a terminat
LCD_writeInstruction(LCD_INSTR_4wire); // Incarcam comanda: 4 bit data, 2 lines, 5x8 font
LCD_writeInstruction(LCD_INSTR_display); // Display On, Cursor On, Blinking On
LCD_writeInstruction(0x06); // Increment, no shift
LCD_writeInstruction(0x01); // Clear Display
}
void LCD_writeInstruction(unsigned char _instruction)
{
LCD_waitNotBusy(); // asteptam ca LCD-ul sa fie liber sa primeasca comenzile
LcdCMD_PORT &= ~(1 << LcdRS); // setam pinul RS pe low.. low=instructiuni, high=date
LcdCMD_PORT &= ~(1 << LcdRW); // setam pinul RW pe low (suntem in modul de comenzi acum)
LCD_write(_instruction); // apelam procedura ce trimite byte-ul pe firele de date
}
void LCD_writeData(unsigned char _data)
{
LCD_waitNotBusy(); // asteptam ca LCD-ul sa fie liber sa primeasca comenzile
LcdCMD_PORT |= (1 << LcdRS); // setam pinul RS pe high
LcdCMD_PORT &= ~(1 << LcdRW); // setam pinul RW pe low (suntem in modul de comenzi acum)
LCD_write(_data); // apelam procedura ce trimite byte-ul pe firele de date
}
void LCD_write(unsigned char _byte)
{
unsigned char _byte2;
_byte2 = _byte>>4;
LcdDATA_PORT &= ~(1<<LcdD4);
if ( bit_is_set( _byte2, 0 ) )
LcdDATA_PORT |= (1<<LcdD4);
LcdDATA_PORT &= ~(1<<LcdD5);
if ( bit_is_set( _byte2, 1 ) )
LcdDATA_PORT |= (1<<LcdD5);
LcdDATA_PORT &= ~(1<<LcdD6);
if ( bit_is_set( _byte2, 2 ) )
LcdDATA_PORT |= (1<<LcdD6);
LcdDATA_PORT &= ~(1<<LcdD7);
if ( bit_is_set( _byte2, 3 ) )
LcdDATA_PORT |= (1<<LcdD7);
LcdCMD_PORT |= (1<<LcdE); // Setam Pinul E pe high
LCD_waitInstructions(6); // Asteptam o perioada de timp T
LcdCMD_PORT &= ~(1<<LcdE); // Setam Pinul E pe low
LCD_waitInstructions(6); // Asteptam o perioada de timp T
LcdDATA_PORT &= ~(1<<LcdD4);
if ( bit_is_set( _byte, 0 ) )
LcdDATA_PORT |= (1<<LcdD4);
LcdDATA_PORT &= ~(1<<LcdD5);
if ( bit_is_set( _byte, 1 ) )
LcdDATA_PORT |= (1<<LcdD5);
LcdDATA_PORT &= ~(1<<LcdD6);
if ( bit_is_set( _byte, 2 ) )
LcdDATA_PORT |= (1<<LcdD6);
LcdDATA_PORT &= ~(1<<LcdD7);
if ( bit_is_set( _byte, 3 ) )
LcdDATA_PORT |= (1<<LcdD7);
LcdCMD_PORT |= (1<<LcdE); // Setam Pinul E pe high
LCD_waitInstructions(6); // Asteptam o perioada de timp T
LcdCMD_PORT &= ~(1<<LcdE); // Setam Pinul E pe low
}
void LCD_waitNotBusy()
{
unsigned char _loop = 1;
while (_loop)
{
LcdDATA_DDR &= ~(1<<LcdD4 | 1<<LcdD5 | 1<<LcdD6 | 1<<LcdD7); // Setam pinii de date de la LCD pe in pt a citi busy flag
LcdDATA_PORT &= ~(1<<LcdD4 | 1<<LcdD5 | 1<<LcdD6 | 1<<LcdD7); // Dezactivam pullup resistor pentru pinii de in
LcdCMD_PORT &= ~(1<<LcdE); // Setam pin-ul e pe low; ar trebui sa fie deja low, doar ne asiguram
LcdCMD_PORT &= ~(1<<LcdRS); // Setam pinul RS pe low
LcdCMD_PORT |= (1<<LcdRW); // Setam pinul RW pe high (acum suntem in modul de interogare busy/adr)
LcdCMD_PORT |= (1<<LcdE); // Setam Pinul E pe high
LCD_waitInstructions(6); // Asteptam o perioada de timp T
_loop = LcdDATA_PIN & (1<<LcdD7); // Citim busy flag-ul
LcdCMD_PORT &= ~(1<<LcdE); // Setam Pinul E pe low
LCD_waitInstructions(6); // Asteptam o perioada de timp T
LcdCMD_PORT |= (1<<LcdE); // Setam Pinul E pe high
LCD_waitInstructions(6); // Asteptam o perioada de timp T
LcdCMD_PORT &= ~(1<<LcdE); // Setam Pinul E pe low
LcdDATA_DDR |= (1<<LcdD4 | 1<<LcdD5 | 1<<LcdD6 | 1<<LcdD7); // Setam Portul de LCD ca port de iesire la loc
}
}
void LCD_waitInstructions(unsigned char _instructions)
{
while (_instructions--)
;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -