Ошибки В i2c обмен Atmega88 -> Atmega8

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

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

К отданному из проектов решил прикрутить LCD экран МТ12864 на чипе (KS0108).
проблем огребся по самое не хочу т.к его нужно было повернуть на 90 градусов и подключить уже к готовому устройству.
Решением было сделать драйвер для этого экрана на AtMega8 и принимать данные по i2c.
Разобравшись с подключением ,кодировкой , встал вопрос о шине данных как мне казалось я его заставил работать.
Мастер был АтМега88 , слейв Atmega8.
И все вроде-бы работает, пока не добавляю обработчик прерываний на AtMega8.
В чем проблемма не могу понять (.
Но выглядит она след образом:
Идет обмен пакетами мастер -> слейв, и обмен прекращается спустя 50-70 посылок.

Может кто подсказать в какую сторону копать ? (ошибка в мастере или слейве)

Код Слейва:
Спойлер

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

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <util/twi.h>
#include <avr/interrupt.h>
#include <stdlib.h>

#define data_port PORTD
#define data_ddr DDRD
#define cmd_port PORTB
#define cmd_ddr DDRB
#define DCS1 0
#define DCS2 1
#define DI 2
#define RW 3
#define E 4
#define RST 5

#define I2C_ADDR 0x30
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;
	}
}
volatile uint8_t data1=0;
volatile uint8_t data[6][3]={0};
volatile uint8_t flagStepFF=1;
volatile uint8_t flagJump=0;
volatile uint8_t flagCompleteReceiv=0;
volatile uint8_t FlagCompleteFill=0;
void I2C_received(uint8_t received_data)
{
	switch (flagStepFF)
	{
		case 1: if(received_data==0xFF) flagStepFF=2;break;
		case 2: if(received_data==0xFF) flagStepFF=3;break;
		case 3:
			if(received_data==0x00) {data[0][0]=received_data; flagStepFF=4;}
			if(received_data==0x01) {data[1][0]=received_data; flagStepFF=5;}
			if(received_data==0x02) {data[2][0]=received_data; flagStepFF=6;}
			if(received_data==0x03) {data[3][0]=received_data; flagStepFF=7;}
			if(received_data==0x04) {data[4][0]=received_data; flagStepFF=8;}
			if(received_data==0x05) {data[5][0]=received_data; flagStepFF=9;}
			flagJump=1;
		break;
		case 4:
			if(flagJump==0) {data[flagStepFF-4][2]=received_data;flagStepFF=1;break;}
			data[0][1]=received_data;
			flagJump=0;
		break;
		case 5:
			if(flagJump==0) {data[flagStepFF-4][2]=received_data;flagStepFF=1;break;}
			data[1][1]=received_data;
			flagJump=0;
		break;
		case 6:
			if(flagJump==0) {data[flagStepFF-4][2]=received_data;flagStepFF=1;break;}
			data[2][1]=received_data;
			flagJump=0;
		break;
		case 7:
			if(flagJump==0) {data[flagStepFF-4][2]=received_data;flagStepFF=1;break;}
			data[3][1]=received_data;
			flagJump=0;
		break;
		case 8:
			if(flagJump==0) {data[flagStepFF-4][2]=received_data;flagStepFF=1;break;}
			data[4][1]=received_data;
			flagJump=0;
		break;
		case 9:
			if(flagJump==0) {data[flagStepFF-4][2]=received_data;flagStepFF=1;flagCompleteReceiv=1;break;}
			data[5][1]=received_data;
			flagJump=0;
		break;
	}
	
}
void I2C_requested()
{
	I2C_transmitByte(data1);
}

void setup()
{
	// set received/requested callbacks
	I2C_setCallbacks(I2C_received, I2C_requested);

	// init I2C
	I2C_init(I2C_ADDR);
}

PROGMEM const unsigned char FONTNUMBERS[10][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,0x0F,
	0x0F,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},
};
//uint8_t Nuber[6][3];

uint8_t BufferChar[6][4]={0};

/************************************************************************/
/* Функция отправки команды дисплею. ( lcd_cmd )			            */
/************************************************************************/
void lcd_cmd(unsigned char cmd)
{
	_delay_us(2);
	data_port = cmd;
	_delay_us(1);
	cmd_port |= (1<<E);
	_delay_us(12);
	cmd_port &= ~(1<<E);
	_delay_us(2);
}
/************************************************************************/
/* Функция отправки данных дисплею. ( lcd_data )			            */
/************************************************************************/
void lcd_data(unsigned char data,uint8_t FlagInvert)
{
	_delay_us(2);
	cmd_port |= (1<<DI);
	_delay_us(2);
	if(FlagInvert)
		data_port = data;
	else
		data_port = ~data;
	_delay_us(2);
	cmd_port |= (1<<E);
	_delay_us(12);
	cmd_port &= ~(1<<E);
	_delay_us(2);
	cmd_port &= ~(1<<DI);
	_delay_us(2);
}
/************************************************************************/
/* Функция инициализации дисплея. ( lcd_init )			                */
/************************************************************************/
void lcd_init()
{
	data_ddr = 0xFF;
	cmd_ddr |= (1<<DI)|(1<<RW)|(1<<E)|(1<<DCS1)|(1<<DCS2)|(1<<RST);
	cmd_port |= (1<<RST);
	cmd_port &=~((1<<DCS2)|(1<<DCS1));
	cmd_port |= (1<<DCS1);
	lcd_cmd(0x3F);
	cmd_port &=~((1<<DCS2)|(1<<DCS1));
	cmd_port |= (1<<DCS2);
	lcd_cmd(0x3F);
}
/************************************************************************/
/* Установка курсора на дисплее, ось X. (Верх/Низ) ( set_x )			*/			        
/************************************************************************/
void set_x(unsigned char pos_x)
{
	data_port = pos_x|0xB8;
	_delay_us(2);
	cmd_port |= (1<<E);
	_delay_us(12);
	cmd_port &= ~(1<<E);
	_delay_us(2);
}
/************************************************************************/
/* Установка курсора на дисплее, ось Y. (Лево/Право) ( set_y )			*/
/************************************************************************/
void set_y(unsigned char pos_y)
{
	data_port = pos_y|0x40;
	_delay_us(2);
	cmd_port |= (1<<E);
	_delay_us(12);
	cmd_port &= ~(1<<E);
	_delay_us(2);
}
uint8_t lcd_send_block(uint8_t x,uint8_t y, uint8_t len, uint16_t addr,uint8_t FlagInvert)
{
	uint8_t i,col;

	if(y>63)
	{
		cmd_port &= ~(1<<DCS1);
		cmd_port |= (1<<DCS2);
		col = y-64;
	}
	else
	{
		cmd_port &= ~(1<<DCS2);
		cmd_port |= (1<<DCS1);
		col = y;
	}

	set_x(x);
	set_y(col);
	
	for(i=0;i!=len;i++,addr++,col++)
	{
		if(64==col)
		{
			if(cmd_port == (1<<DCS2))
			{
				return 128;
			}

			col=0;
			cmd_port &= ~(1<<DCS1);
			cmd_port |= (1<<DCS2);
			set_x(x);
			set_y(col);
		}

		lcd_data(pgm_read_byte(addr),FlagInvert);
	}
	return y+len;
}
void lcd_big_number(unsigned char Chip, uint8_t x, uint8_t y, uint16_t number,uint8_t FlagInvert)
{
	x=x*2;
	y=y*16;
	uint8_t i,col;
	uint16_t addr;
	addr= number*32;
	if(Chip == 2)
	{
		cmd_port &= ~(1<<DCS1);
		cmd_port |= (1<<DCS2);
		col = y;
	}
	else
	{
		cmd_port &= ~(1<<DCS2);
		cmd_port |= (1<<DCS1);
		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 avr_init()
{
	DDRC = 0x00;
	sei();
}
void FillBuffer()
{
	uint8_t Value[6];
	for (uint8_t tX = 0; tX < 6; tX++ )
	{
		Value[tX]=data[tX][2];
	}
	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;
			BufferChar[tX][i]	=TempResult;
		}
	}
	for (uint8_t tX = 0; tX < 6; tX++ )
	{
		BufferChar[tX][3]=data[tX][1];
	}
	FlagCompleteFill=1;
	flagCompleteReceiv=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],1);
			else
				lcd_big_number(2,tY,tX-3,BufferChar[tX][tY],0);
		}
	}
}
int main(void)
{
	avr_init();
	lcd_init();
	lcd_cmd(0xC0);
	setup();
	sei();
	while(1)
	{
		
		if(flagCompleteReceiv) FillBuffer();
		if(FlagCompleteFill) UpdateLCD();
	}
	return 0;
}
Мастера :
Спойлер

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

#define F_CPU 8000000UL

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


#define F_SCL 100000UL // SCL frequency
#define Prescaler 1
#define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2)
//General Master staus codes
#define START       0x08    //START has been transmitted
#define REP_START   0x10
#define MT_DATA_ACK 0x28
#define MT_SLA_ACK  0x18

//Master Transmitter staus codes
#define MT_ADR_ACK		0x18   //SLA+W has been tramsmitted and ACK received
#define MT_ADR_NACK		0x20   //SLA+W has been tramsmitted and NACK received
#define MT_DATA_ACK		0x28   //Data byte has been tramsmitted and ACK received
#define MT_DATA_NACK	0x30   //Data byte has been tramsmitted and NACK received
#define MT_ARB_LOST		0x38   //Arbitration lost in SLA+W or data bytes
#define WRITE			0x00
#define READ			0x01
#define READ_END		0x01
#define READ_NOEND		0x00
#define ERROR			0x01
#define SUCCESS			0x00
#define I2C_ADR_SLAVE	0x30
// I2C
static uint8_t send_i2c(uint8_t value);
static uint8_t start_i2c(uint8_t d_adr);
static inline void stop_i2c();
static uint8_t write_i2c(uint8_t ADR, uint8_t value);

void i2c_init(void)
{
	TWBR = (uint8_t)TWBR_val;
}
//-------------------------------------------///init_pwm///-----------------------------------------------------------------//
void init_pwm()
{
	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 init_int0()
{
	//настраиваем на срабатывание INT0 по переднему фронту
	EICRA |= (1<<ISC01)|(0<<ISC00);
	//разрешаем внешнее прерывание INT0
	EIMSK |= (1<<INT0);
}
//--------------------------------------------------------------------------------------------------------------------------//
void init_io()
{
	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)|(1<<PD2)|(1<<PD3)|(1<<PD4)|(1<<PD5)|(1<<PD6)|(1<<PD7);
	PORTD=0x00;
}
//--------------------------------------------------------------------------------------------------------------------------//
//настройка параметров работы функций
#define BTN_LOCK_TIME		30					/*время обработки дребезга в милисекундах (10-100)*/
#define BTN_LONG_TIME		1000				/*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/
//настройки портов
/*порт чтения кнопок*/
#define BTN_PORT			PORTB
#define BTN_DDR				DDRB
#define BTN_PIN				PINB
/*пины чтения кнопок*/
#define BTN_LINE_UP		(1<<5)
#define BTN_LINE_DN		(1<<0)
//#define BTN_LINE_POWER	(1<<5)
//#define BTN_LINE_SW		(1<<0)
//глобальные переменные
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			(1<<3)			/*бит короткого нажатия кнопки SW*/
#define BTN_LONG_UP			(1<<4)			/*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN			(1<<5)			/*бит длинного нажатия кнопки dn*/
#define BTN_LONG_SW			(1<<6)			/*бит короткого нажатия кнопки SW*/
//-------------------------------------------------------------------------------------------------------------------
//Функция настройки библиотеки работы с кнопками
void BtnInit (void)
{
	BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN);//на ввод
	BTN_PORT |= (BTN_LINE_UP| BTN_LINE_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_PIN & BTN_LINE_UP))		mask = BTN_SHRT_UP;
	if (! (BTN_PIN & BTN_LINE_DN))		mask = BTN_SHRT_DN;
	//if (! (BTN_PIN & BTN_LINE_POWER))	mask = BTN_SHRT_POWER;
	//if (! (BTN_PIN & BTN_LINE_SW))		mask = BTN_SHRT_SW;

	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<<4);			//счетчик досчитал до максимума - устанавливаем биты длинного нажатия
	}
	else{										//клавиша отжата
		if (BtnLockCoun){
			BtnLockCoun --;
			return;								//защелка еще не обнулилась - возврат
		}
		if (! BtnLockBit)						//СТАТИЧЕСКИЙ ВОЗВРАТ
		return;
		BtnLockBit =0;							//отжатие зафиксировано
		if (BtnLongCoun < (BTN_LONG_TIME/10))
		BtnFlags |= BtnLastState;			//установка бита короткого нажатия
		BtnLongCoun = 0;					//сброс счетчика длительности нажатия
	}
}
#define CONFIG_AMOUNT 6
typedef struct
{
	char FlagPower;
	char ValuePWM;
}ConfigurationLamp;

EEMEM ConfigurationLamp E_ConfigLamp[CONFIG_AMOUNT];
ConfigurationLamp ConfigLamp[CONFIG_AMOUNT];

unsigned char ValuePWM[CONFIG_AMOUNT];
unsigned char FlagPower[CONFIG_AMOUNT];

//-----------------------------------------------------------------------------------------------------
void LoadingEEPROM()
{
	eeprom_read_block((void*)ConfigLamp, (void*)E_ConfigLamp, sizeof(ConfigLamp));
	/*
	for (static unsigned char ValueCount = 0; ValueCount < CONFIG_AMOUNT; ValueCount++)
	{
		FlagPower[ValueCount]=ConfigLamp[ValueCount].FlagPower;
		ValuePWM[ValueCount]=ConfigLamp[ValueCount].ValuePWM;
	}
	*/
	for (static unsigned char ValueCount = 0; ValueCount < CONFIG_AMOUNT; ValueCount++)
	{
		FlagPower[ValueCount]=1;
		ValuePWM[ValueCount]=ValueCount*20+15;
	}
	ValuePWM[5]=0xFF;
}

void SaveEEPROM()
{
	for (unsigned char ValueCount = 0; ValueCount < CONFIG_AMOUNT; ValueCount++)
	{
		ConfigLamp[ValueCount].FlagPower=(FlagPower[ValueCount]);
		ConfigLamp[ValueCount].ValuePWM=(ValuePWM[ValueCount]);
	}
	eeprom_update_block((void*)ConfigLamp, (void*)E_ConfigLamp, sizeof(ConfigLamp));
}
//-----------------------------------------------------------------------------------------------------

unsigned char data1 = 0;
unsigned char data2 = 0;
unsigned char count = 0;
unsigned char ZoneNumber=0;
/*
void WriteSeg(unsigned char Number)
{
	data1=ValuePWM[Number]%10;
	data2=ValuePWM[Number]/10;
	PORTB |=(1<<ANOD1);
	PORTD |=(1<<ANOD2);
	PORTD |=(1<<ANOD3);
	segchar(99);
	if(FlagPower[Number]==1)
	{
		count++;
		if (count==1){
			PORTB &= ~(1<<ANOD1);
			segchar(data1);
			PORTD |=(1<<ANOD2);
			PORTD |=(1<<ANOD3);
		}
		if (count==2){
			PORTD &= ~(1<<ANOD2);
			segchar(data2);
			PORTB |=(1<<ANOD1);
			PORTD |=(1<<ANOD3);
		}
		if (count==3){
			PORTD &= ~(1<<ANOD3);
			segchar(Number+1);
			PORTB |=(1<<ANOD1);
			PORTD|=(1<<ANOD2);
		}
		if (count==3){count=0;}
	}
}
*/
void UpdateValue(void)
{
	for (unsigned char ValueCount = 0; ValueCount < CONFIG_AMOUNT; ValueCount++)
	{
		unsigned char TempValue=0;
		switch (ValueCount)
		{
			case 0:
			TempValue=OCR0A*2.56;
			if (FlagPower[ValueCount]==1)
			{
				if ((TempValue==0)&(!(ValuePWM[ValueCount]==0)))
				{
					while ((TempValue<ValuePWM[ValueCount])& (ValuePWM[ValueCount] < 99))
					{
						//WriteSeg(ZoneNumber);
						TempValue++;
						_delay_ms(100);
						OCR0A=TempValue;
					}
				}
				OCR0A=ValuePWM[ValueCount]*2.56;
			}
			else{
				OCR0A=0;
			}break;
			case 1:
			if (FlagPower[ValueCount]==1)
			{
				OCR0B=ValuePWM[ValueCount]*2.56;
			}
			else{
			OCR0B=0;}break;
			case 2:
			if (FlagPower[ValueCount]==1)
			{
				OCR1AL=ValuePWM[ValueCount]*2.56;
			}
			else{
				OCR1AL=0;
			}break;
			case 3:
			if (FlagPower[ValueCount]==1)
			{
				OCR1BL=ValuePWM[ValueCount]*2.56;
			}
			else{
				OCR1BL=0;
			}break;
			case 4:
			if (FlagPower[ValueCount]==1)
			{
				OCR2A=ValuePWM[ValueCount]*2.56;
			}
			else{
				OCR2A=0;
			}break;
			case 5:
			if (FlagPower[ValueCount]==1)
			{
				OCR2B=ValuePWM[ValueCount]*2.56;
			}
			else{
				OCR2B=0;
			}break;
		}
	}
}
ISR(INT0_vect)
{
	//WriteSeg(ZoneNumber);
	BtnExe();
}
unsigned char fBtnPower=0;
void BtnUpdate(void)
{
	char BtnMask = BtnGet ();
	if (BtnMask == BTN_SHRT_POWER)
	{
		FlagPower[ZoneNumber]++;
		if (FlagPower[ZoneNumber]>1)
		{
			FlagPower[ZoneNumber]=0;
		}
		SaveEEPROM();
	}
	if ((BtnMask == BTN_SHRT_SW))
	{
		ZoneNumber++;
		if (ZoneNumber==6)
		{
			ZoneNumber=0;
		}
	}
	//одиночное нажатие +
	if ((BtnMask == BTN_SHRT_UP)& (ValuePWM[ZoneNumber] < 99))
	{
		ValuePWM[ZoneNumber]++;
		SaveEEPROM();
	}
	//одиночное нажатие -
	if ((BtnMask == BTN_SHRT_DN)& (ValuePWM[ZoneNumber] > 0))
	{
		ValuePWM[ZoneNumber]--;
		SaveEEPROM();
	}
	//Удержание +
	if ((BtnMask == BTN_LONG_UP) & (ValuePWM[ZoneNumber] < 99))
	{
		while ((!(PINB&0b10000000))& (ValuePWM[ZoneNumber] < 99))
		{
			ValuePWM[ZoneNumber]++;
			_delay_ms(50);
		}
		SaveEEPROM();
	}
	//Удержание -
	if ((BtnMask == BTN_LONG_DN) & (ValuePWM[ZoneNumber] > 0))
	{
		while ((!(PINB&0b01000000))& (ValuePWM[ZoneNumber] > 0))
		{
			ValuePWM[ZoneNumber]--;
			_delay_ms(50);
		}
		SaveEEPROM();
	}
}
static uint8_t SendByte_i2c(uint8_t value)
{
	write_i2c((I2C_ADR_SLAVE<<1), value);
	asm("NOP");
	return 0;
}
uint8_t SendDataPack()
{
	for (unsigned char ValueCount = 0; ValueCount < CONFIG_AMOUNT; ValueCount++)
	{
		SendByte_i2c(0xFF);
		SendByte_i2c(0xFF);
		SendByte_i2c(ValueCount);
		SendByte_i2c(FlagPower[ValueCount]);
		SendByte_i2c(ValuePWM[ValueCount]);
		
	}
	return 0;
}
//char i=0;
int main(void)
{
	LoadingEEPROM();
	_delay_ms(50);
	init_io();
	init_int0();
	BtnInit();
	i2c_init();
	init_pwm();
	sei();
	while(1)
	{
		BtnUpdate();
		UpdateValue();
		SendDataPack();
	}
	return 0;
}
// I2C ////////////////////////////////////////
static uint8_t write_i2c(uint8_t ADR, uint8_t value) {
	uint8_t ret;
	if (start_i2c(ADR) != ERROR)
	{
		ret=send_i2c(value);
		stop_i2c();
		} else {
		stop_i2c();
		ret=ERROR;
	}
	return ret;
}
uint8_t send_i2c(uint8_t value)
{
	TWDR = value;
	TWCR = (1<<TWINT) | (1<<TWEN);
	// wail until transmission completed and ACK/NACK has been received
	while(!(TWCR & (1<<TWINT)));
	// check value of TWI Status Register. Mask prescaler bits.

	value = TWSR & 0xF8;
	return (value == MT_SLA_ACK || value == MT_DATA_ACK) ? SUCCESS : ERROR;
}
static uint8_t start_i2c(uint8_t d_adr)
{
	TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // START
	while (!(TWCR & (1<<TWINT)));

	uint8_t twst = (TWSR & 0xF8); // check value of TWI Status Register. Mask prescaler bits.

	return ((twst != START) && (twst != REP_START)) ? ERROR : send_i2c(d_adr);
};
static inline void stop_i2c()
{
	TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}
// END OF FILE ///////////////////////////////
andrei23061996@gmail.com
.................................................................................................................
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4740
Зарегистрирован: Вс янв 24, 2010 13:14:02
Откуда: Омск

Сообщение vem566 »

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

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

Уже тоже понял, время одного цикла (Прием + заполнения буфера + вывод на ЛСД) = почти 30 МС.
andrei23061996@gmail.com
.................................................................................................................
Ответить

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