Чт сен 27, 2018 09:37:51
ConfigLamp[0].ValuePWM=123;
ConfigLamp[0].Flag.Bits.B0=1;
//Структура объеденения битовых полей.
struct UnionsBits
{
unsigned B0:1;
unsigned B1:1;
unsigned B2:1;
unsigned B3:1;
unsigned B4:1;
unsigned B5:1;
unsigned B6:1;
unsigned B7:1;
};
union Byte
{
uint8_t Byte;
struct UnionsBits Bits;
};
#define CONFIG_AMOUNT 1
//Определения нвого типа.
typedef struct {
uint8_t ValuePWM;
union Byte Flag;
}Config;
Config ConfigLamp[CONFIG_AMOUNT]; //Массив структур.
Чт сен 27, 2018 10:05:50
// 31 ConfigLamp[0].ValuePWM=123;
LDI R16, 123
STS ConfigLamp, R16
// 32 ConfigLamp[0].Flag.Bits.B0=1;
LDI R30, LOW(ConfigLamp)
LDI R31, (ConfigLamp) >> 8
LDD R16, Z+1
ORI R16, 0x01
STD Z+1, R16
Чт сен 27, 2018 10:12:34
Чт сен 27, 2018 10:16:45
// 36 return sizeof(Config);
LDI R16, 3
LDI R17, 0
RET
// 36 return sizeof(Config);
LDI R16, 2
LDI R17, 0
RET
Чт сен 27, 2018 10:27:23
struct UnionsBits
{
uint8_t B0:1;
uint8_t B1:1;
uint8_t B2:1;
uint8_t B3:1;
uint8_t B4:1;
uint8_t B5:1;
uint8_t B6:1;
uint8_t B7:1;
};
Чт сен 27, 2018 10:28:04
typedef union{
struct{
uint8_t bit0 : 1;
uint8_t bit1 : 1;
uint8_t bit2 : 1;
uint8_t bit3 : 1;
uint8_t bit4 : 1;
uint8_t bit5 : 1;
uint8_t bit6 : 1;
uint8_t bit7 : 1;
};
uint8_t byte;
} my_data;
my_data d;
d.byte = 0xFF;
d.bit5 = 0;
Чт сен 27, 2018 10:40:44
Чт сен 27, 2018 10:50:05
Чт сен 27, 2018 10:56:55
Чт окт 04, 2018 04:58:23
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <stdint.h>
#include <util/twi.h>
#include <string.h>
//==================
#define SET_BIT(port,bit) port|=(1<<bit)
#define CLEAR_BIT(port,bit) port&= ~(1<<bit)
#define INV_BIT(port,bit) port ^=(1<<bit)
//==================
//настройка параметров работы функций
#define BTN_LOCK_TIME 20 /*время обработки дребезга в милисекундах (10-100)*/
#define BTN_LONG_TIME 1000 /*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/
//настройки портов
/*порт чтения кнопок*/
#define BTN_PORT1 PORTD
#define BTN_DDR1 DDRD
#define BTN_PIN1 PIND
#define BTN_PORT2 PORTB
#define BTN_DDR2 DDRB
#define BTN_PIN2 PINB
/*пины чтения кнопок*/
#define BTN_LINE_UP (1<<7)
#define BTN_LINE_DN (1<<4)
#define BTN_LINE_POWER (1<<2)
#define BTN_LINE_SW_UP (1<<4)
#define BTN_LINE_SW_DN (1<<5)
//глобальные переменные
volatile uint8_t BtnFlags; //байт флагов нажатия кнопки
#define BTN_SHRT_UP (1<<0) /*бит короткого нажатия кнопки up*/
#define BTN_SHRT_DN (1<<1) /*бит короткого нажатия кнопки dn*/
#define BTN_SHRT_POWER (1<<2) /*бит короткого нажатия кнопки POWER */
#define BTN_SHRT_SW_UP (1<<3) /*бит короткого нажатия кнопки SW*/
#define BTN_SHRT_SW_DN (1<<4) /*бит короткого нажатия кнопки SW*/
#define BTN_LONG_UP (1<<5) /*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN (1<<6) /*бит длинного нажатия кнопки dn*/
//#define BTN_LONG_PW (1<<7) /*бит короткого нажатия кнопки SW*/
//==================
#define ADR_SLAVE 0x30 // i2c адрес драйвера LCD
/*размер буфера TWI модуля*/
#define TWI_BUFFER_SIZE 13 //
//****************************************************************************
/*Общие статусные коды */
#define TWI_START 0x08 // состояние START сформировано
#define TWI_REP_START 0x10 // состояние повторный START сформировано
#define TWI_ARB_LOST 0x38 // был потерян приоритет
/*Статусные коды ведущего передатчика*/
#define TWI_MTX_ADR_ACK 0x18 // был передан пакет SLA+W и получено подтверждение
#define TWI_MTX_ADR_NACK 0x20 // был передан пает SLA+W и не получено подтверждение
#define TWI_MTX_DATA_ACK 0x28 // был передан байт данных и получено подтверждение
#define TWI_MTX_DATA_NACK 0x30 // был передан байт данных и не получено подтверждение
/*Статусные коды ведущего приемника*/
#define TWI_MRX_ADR_ACK 0x40 // был передан пакет SLA+R и получено подтвеждение
#define TWI_MRX_ADR_NACK 0x48 // был передан пакет SLA+R и не получено подтверждение
#define TWI_MRX_DATA_ACK 0x50 // байт данных принят и передано подтверждение
#define TWI_MRX_DATA_NACK 0x58 // был принят байт данных без подтверждения
/*Другие статусные коды*/
#define TWI_NO_STATE 0xF8 // неопределенное состояние; TWINT = “0”
#define TWI_BUS_ERROR 0x00 // ошибка на шине из-за некоректных состояний СТАРТ или СТОП
/*Пользовательские коды*/
#define TWI_SUCCESS 0xff
/****************************************************************************
Определения констант
****************************************************************************/
#define TWI_READ_BIT 0 // позиция R/W бита в адресном пакете
#define TWI_ADR_BITS 1 // позиция адреса в адресном пакете
#define TRUE 1
#define FALSE 0
#define TWSR_MASK 0xfc
//==================
//Структура объеденения битовых полей.
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 {
uint8_t ValuePWM; //Значения PWM
union Byte Flag; //Праметры записанные в битовых полях
}Config;
#define CONFIG_AMOUNT 6
Config ConfigPWM[CONFIG_AMOUNT]; //Массив структур.
EEMEM Config E_ConfigPWM[CONFIG_AMOUNT];
uint8_t ValuePWM[CONFIG_AMOUNT]={0};
volatile static uint8_t twiBuf[TWI_BUFFER_SIZE];
volatile static uint8_t twiState = TWI_NO_STATE;
volatile static uint8_t twiMsgSize;
uint8_t BuffTransmitTWI[13]={0};
/*предделители для установки скорости обмена twi модуля*/
uint8_t pre[4] = {2, 8, 32, 128};
/****************************************************************************
Инициализация и установка частоты SCL сигнала
****************************************************************************/
uint8_t TWI_MasterInit(uint16_t fr)
{
uint8_t i;
uint16_t twbrValue;
for(i = 0; i<4; i++){
twbrValue = ((((F_CPU)/1000UL)/fr)-16)/pre[i];
if ((twbrValue > 0)&& (twbrValue < 256)){
TWBR = (uint8_t)twbrValue;
TWSR = i;
TWDR = 0xFF;
TWCR = (1<<TWEN);
return TWI_SUCCESS;
}
}
return 0;
}
/****************************************************************************
Проверка - не занят ли TWI модуль. Используется внутри модуля
****************************************************************************/
static uint8_t TWI_TransceiverBusy(void)
{
return (TWCR & (1<<TWIE));
}
/****************************************************************************
Взять статус TWI модуля
****************************************************************************/
uint8_t TWI_GetState(void)
{
while (TWI_TransceiverBusy());
return twiState;
}
/****************************************************************************
Передать сообщение msg из msgSize байтов на TWI шину
****************************************************************************/
void TWI_SendData(uint8_t *msg, volatile uint8_t msgSize)
{
uint8_t i;
while(TWI_TransceiverBusy()); //ждем, когда TWI модуль освободится
twiMsgSize = msgSize; //сохряняем кол. байт для передачи
twiBuf[0] = msg[0]; //и первый байт сообщения
if (!(msg[0] & (TRUE<<TWI_READ_BIT)))
{ //если первый байт типа SLA+W
for (i = 1; i < msgSize; i++)
{ //то сохряняем остальную часть сообщения
twiBuf[i] = msg[i];
}
}
twiState = TWI_NO_STATE ;
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA); //разрешаем прерывание и формируем состояние старт
}
/****************************************************************************
Переписать полученные данные в буфер msg в количестве msgSize байт.
****************************************************************************/
uint8_t TWI_GetData(uint8_t *msg, uint8_t msgSize)
{
uint8_t i;
while(TWI_TransceiverBusy()); //ждем, когда TWI модуль освободится
if(twiState == TWI_SUCCESS){ //если сообщение успешно принято,
for(i = 0; i < msgSize; i++){ //то переписываем его из внутреннего буфера в переданный
msg[i] = twiBuf[i];
}
}
return twiState;
}
/****************************************************************************
Обработчик прерывания TWI модуля
****************************************************************************/
ISR(TWI_vect)
{
volatile static uint8_t ptr;
uint8_t stat = TWSR & TWSR_MASK;
switch (stat){
case TWI_START: // состояние START сформировано
case TWI_REP_START: // состояние повторный START сформировано
ptr = 0;
case TWI_MTX_ADR_ACK: // был передан пакет SLA+W и получено подтверждение
case TWI_MTX_DATA_ACK: // был передан байт данных и получено подтверждение
if (ptr < twiMsgSize){
TWDR = twiBuf[ptr]; //загружаем в регистр данных следующий байт
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT); //сбрасываем флаг TWINT
ptr++;
}
else{
twiState = TWI_SUCCESS;
TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWSTO)|(0<<TWIE); //формируем состояние СТОП, сбрасываем флаг, запрещаем прерывания
}
break;
case TWI_MRX_DATA_ACK: //байт данных принят и передано подтверждение
twiBuf[ptr] = TWDR;
ptr++;
case TWI_MRX_ADR_ACK: //был передан пакет SLA+R и получено подтвеждение
if (ptr < (twiMsgSize-1)){
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA); //если это не предпоследний принятый байт, формируем подтверждение
}
else {
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT); //если приняли предпоследний байт, подтверждение не формируем
}
break;
case TWI_MRX_DATA_NACK: //был принят байт данных без подтверждения
twiBuf[ptr] = TWDR;
twiState = TWI_SUCCESS;
TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWSTO); //формируем состояние стоп
break;
case TWI_ARB_LOST: //был потерян приоритет
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA); // сбрасываем флаг TWINT, формируем повторный СТАРТ
break;
case TWI_MTX_ADR_NACK: // был передан пает SLA+W и не получено подтверждение
case TWI_MRX_ADR_NACK: // был передан пакет SLA+R и не получено подтверждение
case TWI_MTX_DATA_NACK: // был передан байт данных и не получено подтверждение
case TWI_BUS_ERROR: // ошибка на шине из-за некоректных состояний СТАРТ или СТОП
default:
twiState = stat;
TWCR = (1<<TWEN)|(0<<TWIE)|(0<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC); //запретить прерывание
}
}
void WriteDataBuf()
{
/*Копируем массивы структур ConfigPWM в Массив buf со сдвигом на 1ну ячейку */
memcpy(BuffTransmitTWI+1,ConfigPWM,sizeof(BuffTransmitTWI)-1);
}
//----------
void LoadingEEPROM()
{
eeprom_read_block((void*)ConfigPWM, (void*)E_ConfigPWM, sizeof(ConfigPWM));
for (uint8_t CountChannel = 0; CountChannel < CONFIG_AMOUNT; CountChannel++)
{
ValuePWM[CountChannel]=ConfigPWM[CountChannel].ValuePWM;
ConfigPWM[CountChannel].ValuePWM=0;
}
}
void UpdateEEPROM()
{
eeprom_update_block((void*)ConfigPWM, (void*)E_ConfigPWM, sizeof(ConfigPWM));
}
//----------
void InitIO()
{
DDRB=(0<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(0<<PB5)|(0<<PB6)|(0<<PB7);
PORTB=0x00;
DDRC=(1<<PC0)|(1<<PC1)|(1<<PC2)|(1<<PC3)|(1<<PC4)|(1<<PC5)|(1<<PC6);
PORTC=0x00;
DDRD=(1<<PD0)|(1<<PD1)|(0<<PD2)|(1<<PD3)|(1<<PD4)|(1<<PD5)|(1<<PD6)|(1<<PD7);
PORTD=0x00;
}
//----------///init_pwm///----------//
void InitPWM()
{
TCCR0A=(1<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00);
OCR0A=0x00;
OCR0B=0x00;
TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (1<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10);
OCR1AL=0x00;
OCR1BL=0x00;
TCCR2A=(1<<COM2A1) | (0<<COM2A0) | (1<<COM2B1) | (0<<COM2B0) | (1<<WGM21) | (1<<WGM20);
TCCR2B=(0<<WGM22) | (0<<CS22) | (1<<CS21) | (0<<CS20);
OCR2A=0x00;
OCR2B=0x00;
}
//----------//
//Функция настройки библиотеки работы с кнопками
void BtnInit (void)
{
BTN_DDR1 &= ~(BTN_LINE_UP| BTN_LINE_DN|BTN_LINE_POWER);//на ввод
BTN_PORT1 |= (BTN_LINE_UP| BTN_LINE_DN|BTN_LINE_POWER);//подтяжка вкл
BTN_DDR2 &= ~(BTN_LINE_SW_UP|BTN_LINE_SW_DN);//на ввод
BTN_PORT2 |= (BTN_LINE_SW_UP|BTN_LINE_SW_DN);//подтяжка вкл
}
//----------
//Функция чтения данных о нажатии кнопок
char BtnGet (void)
{
cli();
char temp = BtnFlags;
BtnFlags = 0;
sei();
return temp;
}
//----------
//ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании с частотой 100 Гц)
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
void BtnExe (void)
{
static unsigned char BtnLockBit; //защелка (защита от дребезга)
static unsigned char BtnLockCoun; //счетчик защелки (защита от дребезга)
static unsigned char BtnLongCoun; //счетчик длинного нажатия
static unsigned char BtnLastState; //последнее состояние кнопок перед отпусканием
char mask = 0;
if (! (BTN_PIN1 & BTN_LINE_UP)) mask = BTN_SHRT_UP;
if (! (BTN_PIN1 & BTN_LINE_DN)) mask = BTN_SHRT_DN;
if (! (BTN_PIN1 & BTN_LINE_POWER)) mask = BTN_SHRT_POWER;
if (! (BTN_PIN2 & BTN_LINE_SW_UP)) mask = BTN_SHRT_SW_UP;
if (! (BTN_PIN2 & BTN_LINE_SW_DN)) mask = BTN_SHRT_SW_DN;
if (mask){ //опрос состояния кнопки
if (BtnLockCoun < (BTN_LOCK_TIME/10)){ //клавиша нажата
BtnLockCoun++;
return; //защелка еще не дощитала - возврат
}
BtnLastState = mask;
BtnLockBit =1; //нажатие зафиксировано
if (BtnLongCoun >= (BTN_LONG_TIME/10))
return; //возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше
if (++BtnLongCoun >= (BTN_LONG_TIME/10))
BtnFlags |= (BtnLastState<<5); //счетчик досчитал до максимума - устанавливаем биты длинного нажатия
}
else{ //клавиша отжата
if (BtnLockCoun){
BtnLockCoun --;
return; //защелка еще не обнулилась - возврат
}
if (! BtnLockBit) //СТАТИЧЕСКИЙ ВОЗВРАТ
return;
BtnLockBit =0; //отжатие зафиксировано
if (BtnLongCoun < (BTN_LONG_TIME/10))
BtnFlags |= BtnLastState; //установка бита короткого нажатия
BtnLongCoun = 0; //сброс счетчика длительности нажатия
}
}
void CursorCLR()
{
ConfigPWM[0].Flag.Bits.B1=0;
ConfigPWM[1].Flag.Bits.B1=0;
ConfigPWM[2].Flag.Bits.B1=0;
ConfigPWM[3].Flag.Bits.B1=0;
ConfigPWM[4].Flag.Bits.B1=0;
ConfigPWM[5].Flag.Bits.B1=0;
}
#define MAX_VALUE_CHANNEL 220
uint8_t ActiveHeatingZone=0;
uint8_t FlagLongBT=0;
volatile uint8_t FlagEnableIncrement=0;
uint8_t FlagSmoothStart=1;
void BtnUpdate(void)
{
char BtnMask = BtnGet ();
if (BtnMask == BTN_SHRT_POWER)
{
INV_BIT(ConfigPWM[ActiveHeatingZone].Flag.Byte,0);
UpdateEEPROM();
//Если был переход из OFF в ON
if(ConfigPWM[ActiveHeatingZone].Flag.Bits.B0==1)
{
ValuePWM[ActiveHeatingZone]=ConfigPWM[ActiveHeatingZone].ValuePWM;
ConfigPWM[ActiveHeatingZone].ValuePWM=0;
FlagSmoothStart=1;
}
}
//одиночное нажатие +
if ((BtnMask == BTN_SHRT_UP)&&(ConfigPWM[ActiveHeatingZone].Flag.Bits.B0 == 1))
{
if(ConfigPWM[ActiveHeatingZone].ValuePWM<MAX_VALUE_CHANNEL){
ConfigPWM[ActiveHeatingZone].ValuePWM++;
UpdateEEPROM();
}
}
//одиночное нажатие -
if ((BtnMask == BTN_SHRT_DN)&&(ConfigPWM[ActiveHeatingZone].Flag.Bits.B0 == 1))
{
if(ConfigPWM[ActiveHeatingZone].ValuePWM){
ConfigPWM[ActiveHeatingZone].ValuePWM--;
UpdateEEPROM();
}
}
//длинное нажатие нажатие +
if ((BtnMask == BTN_LONG_UP)&&(ConfigPWM[ActiveHeatingZone].Flag.Bits.B0 == 1))
{
FlagLongBT=1;
}
//длинное нажатие нажатие -
if ((BtnMask == BTN_LONG_DN)&&(ConfigPWM[ActiveHeatingZone].Flag.Bits.B0 == 1))
{
FlagLongBT=1;
}
if ((BtnMask == BTN_SHRT_SW_UP))
{
if(ActiveHeatingZone<5) ActiveHeatingZone++;
CursorCLR();
ConfigPWM[ActiveHeatingZone].Flag.Bits.B1=1;
}
if ((BtnMask == BTN_SHRT_SW_DN))
{
if(ActiveHeatingZone>0) ActiveHeatingZone--;
CursorCLR();
ConfigPWM[ActiveHeatingZone].Flag.Bits.B1=1;
}
}
void UpdlngBt()
{
if (FlagLongBT)
{
if((!(PIND&BTN_LINE_UP))||(!(PIND&BTN_LINE_DN)))
{
if(!(PIND&BTN_LINE_UP))
{
if ((FlagEnableIncrement)&&(ConfigPWM[ActiveHeatingZone].ValuePWM<MAX_VALUE_CHANNEL))
{
ConfigPWM[ActiveHeatingZone].ValuePWM++;
FlagEnableIncrement=0;
}
}
if(!(PIND&BTN_LINE_DN))
{
if (FlagEnableIncrement)
{
if(ConfigPWM[ActiveHeatingZone].ValuePWM){
ConfigPWM[ActiveHeatingZone].ValuePWM--;
}
FlagEnableIncrement=0;
}
}
}else
{
UpdateEEPROM();
FlagLongBT=0;
}
}
}
//Функция записи значения PWM
#define CONST_POWER 1.15
void WriteValuePWM(uint8_t Channel,uint8_t ValuePWM)
{
switch (Channel)
{
case 0:OCR0A=(uint8_t)ValuePWM*CONST_POWER;break;
case 1:OCR0B=(uint8_t)ValuePWM*CONST_POWER;break;
case 2:OCR1AL=(uint8_t)ValuePWM*CONST_POWER;break;
case 3:OCR1BL=(uint8_t)ValuePWM*CONST_POWER;break;
case 4:OCR2A=(uint8_t)ValuePWM*CONST_POWER;break;
case 5:OCR2B=(uint8_t)ValuePWM*CONST_POWER;break;
}
}
//Функция считывания значения PWM
char ReadValue(uint8_t Channel)
{
static uint8_t ValuePWM=0;
switch (Channel)
{
case 0:ValuePWM=OCR0A;break;
case 1:ValuePWM=OCR0B;break;
case 2:ValuePWM=OCR1AL;break;
case 3:ValuePWM=OCR1BL;break;
case 4:ValuePWM=OCR2A;break;
case 5:ValuePWM=OCR2B;break;
}
return(ValuePWM/CONST_POWER);
}
/*
Функция обновления значений ШИМ()
{
For(СчетчикКанала=0;СчетчикКанала < 6;СчетчикКанала++)
{
Если(РазрешенПлавныйСтарт)
{
Если(Текущие значение[СчетчикКанала] < заданного значения[СчетчикКанала])
{
Если(Разрешенно Прибавлять)
{
Текущие значение++;
Если(ФлагПитания Активен)
{
записываем значения в регистр шим.;
} Иначе запписываем 0 в регистр шим.;
}
Запретить прибавлять;
}
Если(счетчик == 5)
{
Если(Текущие значение[СчетчикКанала] == задонному значению[СчетчикКанала])
Если(ТекущиеЗНачение[активного канала]==ЗадонномуЗначению[активного канала])
Обнулить РазрешениеПлавногоСтарта;
}
}
Иначе
{
Если(ФлагПитания Активен)
{
записываем значения в регистр шим.;
} Иначе запписываем 0 в регистр шим.;
}
}
}
*/
void UpdateValue(void)
{
for(uint8_t CountChannel=0;CountChannel<CONFIG_AMOUNT;CountChannel++)
{
if(FlagSmoothStart)
{
if(ConfigPWM[CountChannel].ValuePWM < (ValuePWM[CountChannel]))
{
if(FlagEnableIncrement)
{
if(ConfigPWM[CountChannel].Flag.Bits.B0 == 1){
ConfigPWM[CountChannel].ValuePWM++; //Если включен канал шим, то веддем плавный отсчет
}else{
ConfigPWM[CountChannel].ValuePWM=ValuePWM[CountChannel]; //Иначе просто записывает дданые в ОЗУ.
}
if(ConfigPWM[CountChannel].Flag.Bits.B0 == 1)
{
WriteValuePWM(CountChannel,ConfigPWM[CountChannel].ValuePWM);
}
else WriteValuePWM(CountChannel,0x00);
}
FlagEnableIncrement=0;
}
if(CountChannel==5)
{
if(ConfigPWM[CountChannel].ValuePWM == ValuePWM[CountChannel])
if(ConfigPWM[ActiveHeatingZone].ValuePWM == ValuePWM[ActiveHeatingZone])
FlagSmoothStart=0;
}
}
else
{
if(ConfigPWM[CountChannel].Flag.Bits.B0 == 1)
{
WriteValuePWM(CountChannel,ConfigPWM[CountChannel].ValuePWM);
}
else WriteValuePWM(CountChannel,0x00);
}
}
}
void InitStartVarible()
{
CursorCLR();
ConfigPWM[ActiveHeatingZone].Flag.Bits.B1=1;
}
uint8_t CountDIV=7;
uint8_t CountDIV2=2;
int main(void)
{
BuffTransmitTWI[0] = (ADR_SLAVE<<1); //Байт определяющий адрес слейва
TWI_MasterInit(100); //Иницилизация TWI и установка частоты в kHz
LoadingEEPROM();
InitIO();
InitPWM();
BtnInit();
InitStartVarible();
sei();
while(1)
{
UpdateValue();
WriteDataBuf();
TWI_SendData(BuffTransmitTWI,sizeof(BuffTransmitTWI));
if(!(CountDIV--))
{
BtnExe(); //Вызывается раз в 10ms.
if(!(CountDIV2--))
{
FlagEnableIncrement=1;
CountDIV2=2;
}
CountDIV=7; //Делитель
}
BtnUpdate();
UpdlngBt();
}
return 0;
}
#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;
}
Ср окт 10, 2018 07:53:05