Ошибка при обращении к битовому полю.

Обсуждаем контроллеры компании Atmel.
Ответить
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

Есть массив структур ConfigLamp[CONFIG_AMOUNT].
Обращаюсь у нему следующим образом:

Код: Выделить всё

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]; //Массив структур.
andrei23061996@gmail.com
.................................................................................................................
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Да вроде что просили, то и получили. Ничего не должно тереться.

Код: Выделить всё

//   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
Только зачем UnionsBits 16-битная?
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

А с чего вы взяли что UnionsBits 16-битная? просто не понимаю асемблер.

Она должна быть 8 бит. т.к состоит из 8 полей B0..B7.

Добавлено after 1 minute 54 seconds:
тут 16ти битная только ConfigLamp

т.к состоит из 2ух 8мибитных.

typedef struct {
uint8_t ValuePWM;
union Byte Flag;
}Config;
andrei23061996@gmail.com
.................................................................................................................
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Потому что в AVR тип unsigned 16-битный.

PS: И не надо второй раз писать union и struct. Вы и так определили тип Byte как union, а UnionsBits как struct.

Код: Выделить всё

//   36   return sizeof(Config);
        LDI     R16, 3
        LDI     R17, 0
        RET
Если вместо unsigned поставить uint8_t, то будет как и задумано

Код: Выделить всё

//   36   return sizeof(Config);
        LDI     R16, 2
        LDI     R17, 0
        RET
Реклама
Эиком - электронные компоненты и радиодетали
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

Понял о чем вы изменил структуру:
//Структура объеденения битовых полей.

Код: Выделить всё

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;
};
andrei23061996@gmail.com
.................................................................................................................
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

а еще в GCC есть безымянные структуры и юнионы

Код: Выделить всё

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;
количество точек при обращении можно уменьшить :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

Только это не помогает (.
Скрины :

Изображение Изображение Изображение Изображение Изображение hunger games 1 plot

Добавлено after 6 minutes 52 seconds:
То есть с данной структурой взаимодействует всего 2 строчки в теле программы. и не могу понят от куда в нее сыпется весь остальной шлак.
andrei23061996@gmail.com
.................................................................................................................
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Даже разбираться не хочу в том бреде что в TWI_SendData(). Это она гадит тебе по памяти.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

TWI_SendData() не виновата , я ее исключал из цикла.

Добавлено after 2 minutes:
Упс извиняюсь походу это она все таки.
andrei23061996@gmail.com
.................................................................................................................
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

Наконец то выдалось свободное время допилить код. 8)
Т.к сам долго провозился с некоторыми моментами, решил поделиться полной наработкой тут может кому и пригодится :)

Реализация драйвера LCD экрана с управлением по протоколу I2C на AtMega8.
Реализация 6-ти управляемых PWM каналов с последующей передачей информации на LCD экран. на AtMega88.

Мастер AtMega88
Спойлер

Код: Выделить всё

#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;
}

Slave Atmega8
Спойлер

Код: Выделить всё

#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;
}
Схема:
СпойлерИзображение
Картинка:

Изображение

Добавлено after 7 minutes 9 seconds:
А сам Теперь буду думать как сюда прикрутить внешний протокол ModBus ))

Предчувствуя следующий объем кода походу придется добавлять еще один МК с двумя уартами 1 для связи с Мастером AtMega88 2ой уже выход ModBus.
Хотя это только предположения.
Но на данный момент как я думаю вычислительные ресурсы двух мк исчерпаны. (

Добавлено after 31 minute 24 seconds:
Просьба к модераторам данного форума. Если имеется возможность изменить название темы для более детального понимания ее содержания.
Тема: Реализация 6-ти PWM каналов с передачей информации по I2C на LCD Драйвер.
andrei23061996@gmail.com
.................................................................................................................
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

Собрал это дело в железе и столкнулся с интересной проблемой один из чипов экрана после кратковременного отключения(1-10 сек) при повторном включении не выводит изображение(информацию). кто нибудь сталкивался с подобным ?
ВещДоки :)
Изображение
Изображение
Изображение

Добавлено after 2 minutes 19 seconds:
Re: Ошибка при обращении к битовому полю.
Плата грязновата , но для прототипа думаю это не страшно XD
andrei23061996@gmail.com
.................................................................................................................
Ответить

Вернуться в «AVR»