#include "MyLCD.h" // задержеки через асемблер #define lcd_e_delay() __asm__ __volatile__( "rjmp 1f\n 1:" ); #define lcd_e_toggle() toggle_e() volatile uint8_t dataport = 0; static void toggle_e(void); // сама реализация задержек static inline void _delayFourCycles(unsigned int __count) { if ( __count == 0 ) __asm__ __volatile__( "rjmp 1f\n 1:" ); else __asm__ __volatile__ ( "1: sbiw %0,1" "\n\t" "brne 1b" : "=w" (__count) : "0" (__count) ); } // тупа оборачиваем функцию в макрос #define delay(us) _delayFourCycles( ( ( 1*(F_CPU/4000) )*us)/1000 ) // переключение пина для начала записи команды static void toggle_e(void) { pcf8574_setoutputpinhigh(LCD_PCF8574_DEVICEID, LCD_E_PIN); lcd_e_delay(); pcf8574_setoutputpinlow(LCD_PCF8574_DEVICEID, LCD_E_PIN); } // отправка байта для контроллера LCD static void lcd_write(uint8_t data,uint8_t rs) { if (rs) //отправка данных (RS=1, RW=0) dataport |= _BV(LCD_RS_PIN); else // отпрака инструкций(RS=0, RW=0) dataport &= ~_BV(LCD_RS_PIN); dataport &= ~_BV(LCD_RW_PIN); pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport); // отправка старшего полубайта dataport &= ~_BV(LCD_DATA3_PIN); dataport &= ~_BV(LCD_DATA2_PIN); dataport &= ~_BV(LCD_DATA1_PIN); dataport &= ~_BV(LCD_DATA0_PIN); if(data & 0x80) dataport |= _BV(LCD_DATA3_PIN); if(data & 0x40) dataport |= _BV(LCD_DATA2_PIN); if(data & 0x20) dataport |= _BV(LCD_DATA1_PIN); if(data & 0x10) dataport |= _BV(LCD_DATA0_PIN); pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport); lcd_e_toggle(); // отправка младшего полубайта dataport &= ~_BV(LCD_DATA3_PIN); dataport &= ~_BV(LCD_DATA2_PIN); dataport &= ~_BV(LCD_DATA1_PIN); dataport &= ~_BV(LCD_DATA0_PIN); if(data & 0x08) dataport |= _BV(LCD_DATA3_PIN); if(data & 0x04) dataport |= _BV(LCD_DATA2_PIN); if(data & 0x02) dataport |= _BV(LCD_DATA1_PIN); if(data & 0x01) dataport |= _BV(LCD_DATA0_PIN); pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport); lcd_e_toggle(); // завершаем передачу dataport |= _BV(LCD_DATA0_PIN); dataport |= _BV(LCD_DATA1_PIN); dataport |= _BV(LCD_DATA2_PIN); dataport |= _BV(LCD_DATA3_PIN); pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport); } // чтение байта static uint8_t lcd_read(uint8_t rs) { uint8_t data; if (rs) // запись данных (RS=1, RW=0) dataport |= _BV(LCD_RS_PIN); else // запись инструкций (RS=0, RW=0) dataport &= ~_BV(LCD_RS_PIN); dataport |= _BV(LCD_RW_PIN); pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport); pcf8574_setoutputpinhigh(LCD_PCF8574_DEVICEID, LCD_E_PIN); lcd_e_delay(); // чтение страшего полубайта data = pcf8574_getoutputpin(LCD_PCF8574_DEVICEID, LCD_DATA0_PIN) << 4; pcf8574_setoutputpinlow(LCD_PCF8574_DEVICEID, LCD_E_PIN); lcd_e_delay(); pcf8574_setoutputpinhigh(LCD_PCF8574_DEVICEID, LCD_E_PIN); lcd_e_delay(); // чтение младшего полубайта data |= pcf8574_getoutputpin(LCD_PCF8574_DEVICEID, LCD_DATA0_PIN) &0x0F; pcf8574_setoutputpinlow(LCD_PCF8574_DEVICEID, LCD_E_PIN); return data; } // ждем пока ЖК освободится static uint8_t lcd_waitbusy(void) { register uint8_t c; // ждем while ( (c=lcd_read(0)) & (1<= LCD_START_LINE2) && (pos < LCD_START_LINE4) ) addressCounter = LCD_START_LINE3; else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) ) addressCounter = LCD_START_LINE4; else addressCounter = LCD_START_LINE1; #endif lcd_command((1<>4; dataport |= _BV(LCD_DATA0_PIN); // _BV(LCD_FUNCTION_8BIT)>>4; pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport); // дрючим дисплей чтобы он начал работать lcd_e_toggle(); delay(4992); lcd_e_toggle(); delay(64); lcd_e_toggle(); delay(64); // переходим в 4 битный режим dataport &= ~_BV(LCD_DATA0_PIN); pcf8574_setoutput(LCD_PCF8574_DEVICEID, dataport); lcd_e_toggle(); delay(64); lcd_command(LCD_FUNCTION_DEFAULT); // настраиваем кол-во строк lcd_command(LCD_DISP_OFF); // вырубаем дисплей lcd_clrscr(); // чистим экран lcd_command(LCD_MODE_DEFAULT); // запускаемся в стандартном режиме lcd_command(dispAttr); // отправляем настройки }