Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
// E = PORTB3
// RS = PORTB2
// R/W = PORTB1
#define LCD_E (1<<PORTB3)
#define LCD_RS (1<<PORTB1)
#define LCD_RW (1<<PORTB2)
#define LCD_PORT_DDR DDRB
#define LCD_PORT PORTB
#define LCD_PORT_READ PIND
#define LCD_DATA_MASK 0xF0
void LCD_SendNibble(char Nibble, char IsCMD)
{
LCD_PORT_DDR |= LCD_DATA_MASK; // OUT
if (IsCMD)
{
LCD_PORT &= ~LCD_RS; // Instruction
} else {
LCD_PORT |= LCD_RS; // Data
};
LCD_PORT &= ~LCD_RW; // Write
LCD_PORT &= ~LCD_DATA_MASK; // Data...
LCD_PORT |= (Nibble << 4); // Actually, data
_delay_us(100);
LCD_PORT |= LCD_E; // Strobe
_delay_us(300);
LCD_PORT &= ~LCD_E; // Strobe end.
_delay_us(100);
};
void LCD_SendByte(char Data, char IsCMD)
{
LCD_SendNibble(Data>>4, IsCMD);
LCD_SendNibble(Data & 0x0F, IsCMD);
};
char LCD_GetNibble(char IsCMD)
{
char i;
LCD_PORT_DDR &= ~LCD_DATA_MASK; // IN
LCD_PORT |= LCD_DATA_MASK; // Pull-UP
if (IsCMD)
{
LCD_PORT &= ~LCD_RS; // Instruction
} else {
LCD_PORT |= LCD_RS; // Data
};
LCD_PORT |= LCD_RW; // Read
_delay_us(100);
LCD_PORT |= LCD_E; // Strobe
_delay_us(300);
LCD_PORT &= ~LCD_E; // Strobe end.
_delay_us(100);
i = ((LCD_PORT_READ & LCD_DATA_MASK) >> 4);
return i;
};
char LCD_GetByte(char IsCMD)
{
char i;
i = LCD_GetNibble(IsCMD);
i |= (LCD_GetNibble(IsCMD) >> 4);
return i & 0x80;
};
char LCD_IsBusy(void)
{
return LCD_GetByte(1);
};
void LCD_Init(void)
{
DDRB |= 0xFE;
while (LCD_IsBusy());
LCD_SendNibble(0x02, 1);
while (LCD_IsBusy());
LCD_SendByte(0x28, 1);
while (LCD_IsBusy());
LCD_SendByte(0x0F, 1);
while (LCD_IsBusy());
LCD_SendByte(0x06, 1);
while (LCD_IsBusy());
LCD_SendByte(0x80, 1);
while (LCD_IsBusy());
};
while (LCD_IsBusy()); // Дожидаемся, пока экран будет готов
LCD_SendByte(0x85, 1); // Переход на 1 знакоместо 1 строки
for (t_val=0;t_val<i;t_val++) // Перебираем байты в массиве с текстом
{
while (LCD_IsBusy()); // Снова пауза до готовности
LCD_SendByte(data2[t_val], 0); // Передаём символ
}; // Цикл
#define LCD_DATA_MASK 0xF0
//7------0
//1111xxxx - Биты шины данных от старшего к младшему)
//xxxx111x - Биты управления E, RW, RS</source>
0-й бит пуст.
Разберу по порядку инструкции:
LCD_PORT &= ~LCD_DATA_MASK;
LCD_PORT - он же "#define LCD_PORT PORTB" превращается в PORTB
Конструкция вида &= сокращение языка. Подразумевает A = A & B
Символ "~" - побитовая инверсия
LCD_DATA_MASK - тоже константа.
Теперь получаем:
PORTB = PORTB & (~0xF0 = 0x0F)
PORTB = PORTB & 0x0F
PORTB = 0000xxxx
Где xxxx - старое значение пинов.
То есть, обнуляется только верхний ниббл (полубайт).
Термостат-Вольтметр для авто