Код: Выделить всё
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <util/twi.h>
#include <avr/interrupt.h>
#define SET_BIT(port,bit) port|=(1<<bit)
#define CLR_BIT(port,bit) port&= ~(1<<bit)
#define INV_BIT(port,bit) port ^=(1<<bit)
#define LCD_DATA_PORT PORTD
#define LCD_DATA_DDR DDRD
#define LCD_CMD_PORT PORTB
#define LCD_CMD_DDR DDRB
#define CHIP1 0
#define CHIP2 1
#define DI 2
#define RW 3
#define E 4
#define RST 5
#define I2C_ADDR 0x30
uint8_t data1=1;
volatile uint8_t BufferChar[6][3]={0};
//Структура объеденения битовых полей.
struct UnionsBits
{
uint8_t B0:1; // параметр ON\OFF
uint8_t B1:1; // Активнный(выбранный) ШИМ. Для Курсора LCD.
uint8_t B2:1; // RESERV BIT FLAG
uint8_t B3:1; // RESERV BIT FLAG
uint8_t B4:1; // RESERV BIT FLAG
uint8_t B5:1; // RESERV BIT FLAG
uint8_t B6:1; // RESERV BIT FLAG
uint8_t B7:1; // RESERV BIT FLAG
};
union Byte
{
uint8_t Byte;
struct UnionsBits Bits;
};
//Определения нвого типа.
typedef struct {
union Byte Flag; //Праметры записанные в битовых полях
}Config;
#define CONFIG_AMOUNT 6
Config ConfigLCD[CONFIG_AMOUNT]; //Массив структур.
#define CHAR_F 10
uint8_t BufRecivDat[12]={0};
PROGMEM const unsigned char FONTNUMBERS[15][32] = {
//0
{0x00,0x00,0xE0,0xF0,0x38,0x38,0x38,0x38,
0x38,0x38,0x38,0x38,0xF0,0xE0,0x00,0xFE,
0x00,0x00,0x07,0x0F,0x1C,0x1C,0x1C,0x1C,
0x1C,0x1C,0x1C,0x1C,0x0F,0x07,0x00,0x7F},
//1
{0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xC0,0xC0,0xC0,0xC0,0xF0,0xF0,0x00,0xFE,
0x00,0x00,0x03,0x07,0x0F,0x1D,0x19,0x01,
0x01,0x01,0x01,0x01,0x07,0x07,0x00,0x7F},
//2
{0x00,0x00,0xE0,0xF0,0x78,0x38,0x78,0xF0,
0xC0,0x80,0x00,0x00,0xF8,0xF8,0x00,0xFE,
0x00,0x00,0x03,0x07,0x0E,0x1C,0x00,0x00,
0x01,0x03,0x07,0x0E,0x1F,0x1F,0x00,0x7F},
//3
{0x00,0x00,0xE0,0xF0,0x78,0x38,0x38,0xF0,
0xF0,0x38,0x38,0x78,0xF0,0xE0,0x00,0xFE,
0x00,0x00,0x0F,0x1F,0x1C,0x00,0x00,0x07,
0x07,0x00,0x00,0x1C,0x1F,0x0F,0x00,0x7F},
//4
{0x00,0x00,0xE0,0xE0,0xE0,0x60,0x60,0x60,
0xF8,0xF8,0x60,0x60,0x60,0x60,0x00,0xFE,
0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x18,
0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x7F},
//5
{0x00,0x00,0xF8,0xF8,0x00,0x00,0xC0,0xF0,
0x78,0x38,0x38,0x70,0xE0,0xC0,0x00,0xFE,
0x00,0x00,0x1F,0x1F,0x18,0x18,0x1F,0x1F,
0x00,0x00,0x00,0x00,0x1F,0x1F,0x00,0x7F},
//6
{0x00,0x00,0xE0,0xF8,0x38,0x18,0x00,0xE0,
0xF0,0x38,0x18,0x38,0xF0,0xE0,0x00,0xFE,
0x00,0x00,0x0F,0x0F,0x1C,0x18,0x18,0x1B,
0x1F,0x1C,0x18,0x1C,0x0F,0x07,0x00,0x7F},
//7
{0x00,0x00,0xF8,0xF8,0x38,0x38,0x38,0x70,
0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0xFE,
0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,
0x00,0x01,0x03,0x07,0x0E,0x1C,0x00,0x7F},
//8
{0x00,0x00,0xE0,0xF0,0x38,0x18,0x38,0xF0,
0xF0,0x38,0x18,0x38,0xF0,0xE0,0x00,0xFC,
0x00,0x00,0x07,0x0F,0x1C,0x18,0x1C,0x0F,
0x0F,0x1C,0x18,0x1C,0x0F,0x07,0x00,0x7F},
//9
{0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x38,
0xF8,0xD8,0x18,0x38,0xF0,0xE0,0x00,0xFE,
0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x1C,
0x0F,0x03,0x00,0x18,0x1F,0x0F,0x00,0x7F},
//знак F для OFF.
{0x00,0x00,0xF0,0xF0,0x00,0x00,0x00,0xF0,
0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,
0x00,0x00,0x07,0x07,0x06,0x06,0x06,0x07,
0x07,0x06,0x06,0x06,0x0F,0x0F,0x00,0x7F},
//____СИМВОЛЫ ДЛЯ ФОНА___________________
//донышко 11
{0xF0,0xFC,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
//Горловина 12
{0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFC,0xF8,0x80,0x80,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
//Резьба 13
{0xFE,0xFE,0x80,0x80,0xF0,0xF0,0x80,0x80,
0xF0,0xF0,0x80,0x80,0x80,0x80,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00},
//Тело 14
{0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
};
void I2C_init(uint8_t address);
void I2C_stop(void);
void I2C_setCallbacks(void (*recv)(uint8_t), void (*req)());
inline void __attribute__((always_inline)) I2C_transmitByte(uint8_t data)
{
TWDR = data;
}
static void (*I2C_recv)(uint8_t);
static void (*I2C_req)();
void I2C_setCallbacks(void (*recv)(uint8_t), void (*req)())
{
I2C_recv = recv;
I2C_req = req;
}
void I2C_init(uint8_t address)
{
cli();
// load address into TWI address register
TWAR = address << 1;
// set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
sei();
}
void I2C_stop(void)
{
// clear acknowledge and enable bits
cli();
TWCR = 0;
TWAR = 0;
sei();
}
ISR(TWI_vect)
{
switch(TW_STATUS)
{
case TW_SR_DATA_ACK:
// received data from master, call the receive callback
I2C_recv(TWDR);
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_ST_SLA_ACK:
// master is requesting data, call the request callback
I2C_req();
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_ST_DATA_ACK:
// master is requesting data, call the request callback
I2C_req();
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_BUS_ERROR:
// some sort of erroneous state, prepare TWI to be readdressed
TWCR = 0;
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
default:
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
}
}
/************************************************************************/
/* Функция отправки команды дисплею. ( lcd_cmd ) */
/************************************************************************/
void lcd_cmd(unsigned char cmd)
{
_delay_us(2);
LCD_DATA_PORT = cmd;
_delay_us(1);
SET_BIT(LCD_CMD_PORT,E);
_delay_us(8);
CLR_BIT(LCD_CMD_PORT,E);
_delay_us(2);
}
/************************************************************************/
/* Функция отправки данных дисплею. ( lcd_data ) */
/************************************************************************/
void lcd_data(unsigned char data,uint8_t FlagInvert)
{
_delay_us(2);
LCD_CMD_PORT |= (1<<DI);
_delay_us(2);
if(FlagInvert)
{
LCD_DATA_PORT = ~data;
}
else
{
LCD_DATA_PORT = data;
}
_delay_us(2);
LCD_CMD_PORT |= (1<<E);
_delay_us(8);
LCD_CMD_PORT &= ~(1<<E);
_delay_us(2);
LCD_CMD_PORT &= ~(1<<DI);
_delay_us(2);
}
/************************************************************************/
/* Функция инициализации дисплея. ( lcd_init ) */
/************************************************************************/
void lcd_init()
{
LCD_DATA_DDR = 0xFF;
LCD_CMD_DDR |= (1<<DI)|(1<<RW)|(1<<E)|(1<<CHIP1)|(1<<CHIP2)|(1<<RST);
LCD_CMD_PORT |= (1<<RST);
LCD_CMD_PORT &=~((1<<CHIP2)|(1<<CHIP1));
LCD_CMD_PORT |= (1<<CHIP1);
lcd_cmd(0x3F);
LCD_CMD_PORT &=~((1<<CHIP2)|(1<<CHIP1));
LCD_CMD_PORT |= (1<<CHIP2);
lcd_cmd(0x3F);
}
/************************************************************************/
/* Установка курсора на дисплее, ось X. ( set_x ) */
/************************************************************************/
void set_x(unsigned char pos_x)
{
LCD_DATA_PORT = pos_x|0xB8;
_delay_us(2);
LCD_CMD_PORT |= (1<<E);
_delay_us(8);
LCD_CMD_PORT &= ~(1<<E);
_delay_us(2);
}
/************************************************************************/
/* Установка курсора на дисплее, ось Y. ( set_y ) */
/************************************************************************/
void set_y(unsigned char pos_y)
{
LCD_DATA_PORT = pos_y|0x40;
_delay_us(2);
LCD_CMD_PORT |= (1<<E);
_delay_us(8);
LCD_CMD_PORT &= ~(1<<E);
_delay_us(2);
}
void lcd_big_number(uint8_t Chip, uint8_t x, uint8_t y, uint8_t number,uint8_t FlagInvert)
{
x=x*2;
y=y*16;
uint8_t i,col;
uint16_t addr;
addr= (uint16_t)number*32;
if(Chip == 2)
{
LCD_CMD_PORT &= ~(1<<CHIP1);
LCD_CMD_PORT |= (1<<CHIP2);
col = y;
}
else
{
LCD_CMD_PORT &= ~(1<<CHIP2);
LCD_CMD_PORT |= (1<<CHIP1);
col = y;
}
set_x(x);
set_y(col);
for(i=0;i<32;i++,addr++,col++)
{
if (i == 16)
{
col=y;
x= x+1;
set_x(x);
set_y(col);
}
else
{
set_y(col);
}
lcd_data(pgm_read_byte((uint16_t)FONTNUMBERS+addr),FlagInvert);
}
}
void RenderBackGround()
{
lcd_big_number(1,3,1,11,0);
lcd_big_number(1,3,2,14,0);
lcd_big_number(1,3,3,14,0);
lcd_big_number(2,3,0,14,0);
lcd_big_number(2,3,1,14,0);
lcd_big_number(2,3,2,12,0);
lcd_big_number(2,3,3,13,0);
}
void FillBuffer()
{
uint8_t Value[6];
for (uint8_t tX = 0; tX < 6; tX++ )
{
/*Достаем кажддое второе число из массива получееного
по и2с , для дальнейшего преобразования в три символа.*/
Value[tX]=BufRecivDat[tX*2];
//Параметры из буфера
ConfigLCD[tX].Flag.Byte=BufRecivDat[tX*2+1];
}
for (uint8_t tX = 0; tX < 6; tX++ )
{
uint8_t TempResult=0;
for (uint8_t i = 0; i < 3; i++)
{
TempResult =Value[tX] % 10;
Value[tX] =Value[tX] / 10;
/*Записываем результат преобразования
разбитя числа в буффер вывода на экран */
if (ConfigLCD[tX].Flag.Bits.B0){
BufferChar[tX][i] =TempResult;
}else{
BufferChar[tX][i]=CHAR_F;
BufferChar[tX][2]=0;
}
}
}
}
void UpdateLCD()
{
for (uint8_t tX = 0; tX < 6 ; tX++ )
{
for (uint8_t tY = 0; tY < 3; tY++ )
{
if(tX<3)
//Выводим символы на первый чип
lcd_big_number(1,tY,tX+1,BufferChar[tX][tY],ConfigLCD[tX].Flag.Bits.B1);
else
////Выводим символы на второй чип
lcd_big_number(2,tY,tX-3,BufferChar[tX][tY],ConfigLCD[tX].Flag.Bits.B1);
}
}
}
uint8_t BufCount=0;
void I2C_received(uint8_t received_data)
{
if (BufCount < 12)
{
BufRecivDat[BufCount] = received_data;
BufCount++;
if(BufCount >= 12) BufCount=0;
}
}
void I2C_requested()
{
I2C_transmitByte(data1);
}
void setup()
{
// set received/requested callbacks
I2C_setCallbacks(I2C_received, I2C_requested);
// init I2C
I2C_init(I2C_ADDR);
}
void avr_init()
{
DDRC = 0x00;
sei();
}
int main(void)
{
avr_init();
lcd_init();
lcd_cmd(0xC0);
setup();
RenderBackGround();
sei();
while(1)
{
FillBuffer();
UpdateLCD();
}
return 0;
}