/* Připojení LCD HD44780 k PIC16F628A,externí krystal 8MHz LCD připojen na PORTB,4bit komunikace Teploměr DS18S20 s přesností 0,5°C,připojen k PORTA.PA0 */ #include #define _XTAL_FREQ 8000000 #include // Fuse bity __CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_ON & LVP_OFF & CPD_OFF & CP_OFF); //====================================== #define LCD_PORT PORTB #define LCD_TRIS TRISB #define RS PORTBbits.RB2 #define EN PORTBbits.RB3 #define DQ PORTAbits.RA0 #define DS TRISAbits.TRISA0 #define LCD_HOME 0x02 #define LCD_CLR 0x01 //========================================== // 1wire sběrnice //========================================= //Příkaz reset char Ow_Reset(void) { unsigned char PRESEN; DS = 0; //PA0 = výstup DQ = 0; //PA0 = L __delay_us(480); DS = 1; //PA0 = vstup __delay_us(65); PRESEN = 0; //Pokud je připojeno čidlo PRESEN = 1 if(DQ == 0) { PRESEN = 1; } __delay_us(480); return PRESEN; } //Read byte char Ow_Read(void) { unsigned char byte = 0; for(unsigned char i=0;i<8;i++) { DS = 0; //PA0 = výstup DQ = 0; //PA0 = L __delay_us(5); DS = 1; //PA0 = vstup __delay_us(10); if(DQ > 0) { byte|=1< 0) { DS = 0; //PA0 = výstup DQ = 0; //PA0 = L __delay_us(5); DS = 1; //PA0 = vstup __delay_us(65); } else { DS = 0; //PA0 = výstup DQ = 0; //PA0 = L __delay_us(60); DS = 1; //PA0 = vstup __delay_us(10); } } } //======================================= // LCD 4bit komunikace //====================================== void Strobe(void) { EN = 1; __delay_us(100); EN = 0; __delay_us(100); } //Příkaz void Lcd_Cmd(unsigned char Cmd) { LCD_PORT = (Cmd & 0xF0); //maskuj dolní 4bity RS = 0; //RS = 0(příkaz) Strobe(); LCD_PORT = (Cmd & 0x0F)<<4;//maskuj horní 4bity a posun o 4místa vlevo RS = 0; //RS = 0(příkaz) Strobe(); /* Pokud je výsledek v podmínce nula, jedná se o příkaz "Vymaž dislej" nebo "Návrat na začátek", které vyžadují delší interval */ if (Cmd & 0b11111100) __delay_us(100);else __delay_ms(2); } //Data void Lcd_Chr(unsigned char Chr) { LCD_PORT = (Chr & 0xF0); RS = 1; //RS = 1(data) Strobe(); LCD_PORT = (Chr & 0x0F)<<4; RS = 1; //RS = 1(data) Strobe(); } //inicializace LCD void Lcd_Init(void) { __delay_ms(15); //čekej 15ms //Nastavení PORTu na výstup LCD_TRIS = 0b00000011; //zapiš 03h 8bitová komunikace LCD_PORT = 0b00110000; Strobe(); __delay_ms(5); //čekej > 4,1ms //zapiš 03h 8bitová komunikace Strobe(); //zapiš 03h 8bitová komunikace Strobe(); //4bitová komunikace LCD_PORT = 0b00101011; Strobe(); Lcd_Cmd(0b00101000); //dva řádky Lcd_Cmd(0b00000001); //smaž LCD Lcd_Cmd(0b00001100); //zapni LCD Lcd_Cmd(0b00000110); //incrementace } //Výpis řetězce void Lcd_Out(const char *str) { unsigned char x = 0; while(str[x]!=0) { __delay_us(100); Lcd_Chr(str[x]); x++; } } //Nastavení ukazatele na pozici x(1..2),y(0..15) void Lcd_Gotoxy(unsigned char row,unsigned char col) { switch(row) { case 1:row=0x00;break; case 2:row=0x40;break; } Lcd_Cmd(0b10000000 | row | col); } //================================================== //================================================== // Hlavní program //================================================== void main(void) { unsigned int temp; unsigned int teplota; unsigned char scratchpad[2]; unsigned char Error; char text[] ="000.0"; CMCON = 0b00000111; Lcd_Init(); Lcd_Out("Teplomer s "); Lcd_Gotoxy(2,0); Lcd_Out("DS18S20"); __delay_ms(300); Lcd_Cmd(LCD_CLR); Lcd_Cmd(LCD_HOME); while(1) { Error = Ow_Reset(); if (Error == 1) { Ow_Write(0xCC); //Přeskoč čtení ROM Ow_Write(0x44); //Zahájení převodu __delay_ms(400); //Doba převodu } Error = Ow_Reset(); if (Error == 1) { Ow_Write(0xCC); //Přeskoč čtení ROM Ow_Write(0xBE); //Čtení scratchpadu //Načtení a uložení obsahu scratchpadu scratchpad[0]=Ow_Read(); scratchpad[1]=Ow_Read(); teplota = (scratchpad[1]<<8)|scratchpad[0]; text[0] = ' '; //Zobrazení "-" při teplotě < 0°C if(teplota & 0x8000) { text[0] = '-'; teplota = ~teplota + 1; } temp = teplota >> 1; Lcd_Gotoxy(1,0); Lcd_Out("Teplota:"); if ((temp/100) > 0) { text[0] = 49; } else { if(text[0] != '-') { text[0] = ' '; //Nezobrazení nuly v řádů stovek } } text[1] = ((temp%100)/10) + 48 ; //Výpočet desitek if ((text[1] == 48)&&(text[0] != 49)) { text[1] = ' '; } text[2] = ((temp%100)%10) + 48 ; //Výpočet jednotek //Výpočet desetin temp = (teplota & 0x01) * 5; text[4] = temp + 48; Lcd_Out(text); Lcd_Chr(0xDF); //Zobrazení ° Lcd_Chr(0x43); //Zobrazení C } else { //Error Lcd_Cmd(LCD_HOME); Lcd_Gotoxy(1,0); Lcd_Out("DS18S20 = Error"); //čidlo nezapojeno } } }