Скорость обмена данными UART + l2c

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

Народ помогите увеличить скорость считки данных с eeprom, а то она очень медленная. вот код.

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


#include <mega168.h>
#include <stdio.h>
#include <delay.h>



// I2C Bus functions
#asm
   .equ __i2c_port=0x08 ;PORTC
   .equ __sda_bit=0
   .equ __scl_bit=1
#endasm
#include <i2c.h>

#ifndef RXB8
#define RXB8 1
#endif

#ifndef TXB8
#define TXB8 0
#endif

#ifndef UPE
#define UPE 2
#endif

#ifndef DOR
#define DOR 3
#endif

#ifndef FE
#define FE 4
#endif

#ifndef UDRE
#define UDRE 5
#endif

#ifndef RXC
#define RXC 7
#endif

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

volatile unsigned int addr;
volatile unsigned char pageSize;                                 
volatile bit page_stop_status;


void meny(){
putchar(13); 
putchar(10);
printf("1.Read eeprom");
putchar(13);
putchar(10);
}

void page_stop() 
 {
i2c_stop(); 
delay_ms(30);
page_stop_status=1; 
}


void addr_save(){      // запись счетчиа байт

	i2c_start(); 
	i2c_write(0xa0);
	i2c_write(0); 
	i2c_write(0 & 0x00FF); 
                           
	i2c_write((addr>>8) & 0xFF);
	i2c_write((addr & 0xFF));   // адрес байта
	i2c_write(pageSize);        // номер байта в странице
	page_stop();
} 

void readaddr()        {      // чтение счетчиа байт

unsigned char hi_addr,lo_addr;

i2c_start();               // I2C start signal
i2c_write(0xA0);              // send byte via I2C  (device address + W)
i2c_write(0>>8); 
i2c_write(0 & 0x00FF); 

i2c_start();               // I2C signal repeated start
i2c_write(0xA1);             // send byte (device address + R)
hi_addr = i2c_read(0); // Read the data (NO acknowledge)   


i2c_start();               // I2C signal repeated start
i2c_write(0xA1);             // send byte (device address + R)
lo_addr = i2c_read(0); // Read the data (NO acknowledge)   

i2c_start();               // I2C signal repeated start
i2c_write(0xA1);             // send byte (device address + R)
pageSize = i2c_read(0); // Read the data (NO acknowledge)   

addr=hi_addr;
addr=(addr<<8);           // собираем млатший и старший байт
addr=(addr | lo_addr); 

 page_stop();
 
}

void ReadMem(){          // читать память

unsigned int cnt;
unsigned int temp_addr;

readaddr(); 

if (addr==3) {putchar('E'); putchar('m'); putchar('t'); putchar('y');putchar(' '); putchar('M'); putchar('e'); putchar('m'); putchar('o');putchar('r'); putchar('y'); 
putchar(13);
putchar(10);
putchar(13);
putchar(10);}


else {

putchar('R'); putchar('e'); putchar('a'); putchar('d');putchar('i'); putchar('n');  putchar('g');
putchar(13);
putchar(10);
LED_ON; 


temp_addr=3;
while (temp_addr<addr) {
i2c_start(); 
i2c_write(0xa0);
i2c_write(temp_addr>>8); 
i2c_write(temp_addr & 0x00FF);   

for(cnt=0;cnt<128;cnt++)    {  
i2c_start();               // I2C signal repeated start
i2c_write(0xA1);             // send byte (device address + R)
putchar(i2c_read(0)); 
temp_addr++;
if (temp_addr==addr) 
 break;                 
} // Read the data (NO acknowledge)  
                            
page_stop();        
 }
                                       
                      
page_stop();


putchar(13);
putchar(10);
LED_OFF; 
putchar('O'); putchar('k'); 
                            } 
putchar(13);
putchar(10);
meny();        

} 

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) {

if (data=='1') ReadMem();

}
}

void main(void)
{

PORTB=0xFF;
DDRB=0x00;

// Port C initialization
PORTC=0x7F;
DDRC=0x00;

// Port D initialization

PORTD=0xE0;
DDRD=0x00;   



// External Interrupt(s) initialization
// INT0: On
EICRA=0x00;
EIMSK=0x00;
EIFR=0x00;
PCICR=0x00;

// Clock value: 31.250 kHz
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x01;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;

// USART Baud Rate: 1200    
UCSR0A=0x00;
UCSR0B=0x98;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x33;


// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR1=0x00;

// ADC disabled
ADCSRA=0x00;

// SPI disabled
SPCR=0x00;

// TWI disabled
TWCR=0x00;


/* Prepare the sleep in power save mode*/
SMCR |= ((1<<SE) | (0<<SM2) | (0<<SM1) | (0<<SM0)); 
/* Enter sleep mode */



i2c_init(); // включаем память  
delay_ms(100);


readaddr(); 
if (addr==65535) addr=pageSize=3;
addr_save();
page_stop(); 

meny();

#asm("sei") 

#pragma optsize-
#asm("wdr")
WDTCSR=0x39;
WDTCSR=0x29;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

delay_ms(100);

while (1)



    {
     page_stop(); 
     addr_save(); 

      }
}

Последний раз редактировалось kotriks Вс апр 07, 2013 13:04:24, всего редактировалось 1 раз.
Реклама
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Сообщение Vov123 »

Чтение с любой eeprom процедура продолжительная,а запись вообще...
Реклама
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Сообщение uk8amk »

Первым делом перейти на аппаратный I2C(у атмеля TWI).
Программный ногодрыг через <i2c.h> работает действительно крайне медленно.
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

kotriks писал(а):помогите увеличить скорость считки данных с eeprom, а то она очень медленная.
...читайте и пишите блоками. 100 и 400Kb ИМХО вполне достижимо для чтения.
uk8amk писал(а):Первым делом перейти на аппаратный I2C(у атмеля TWI).
Программный ногодрыг через <i2c.h> работает действительно крайне медленно.
... программная работа ни чуть не медленнее, просто больше загрузка МК...
Реклама
Эиком - электронные компоненты и радиодетали
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

ChipKiller писал(а):
kotriks писал(а):помогите увеличить скорость считки данных с eeprom, а то она очень медленная.
...читайте и пишите блоками. 100 и 400Kb ИМХО вполне достижимо для чтения.
можете показать пример как это реализовать, а то я не шибко в этом понимаю.
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

в datashete на любую 24cxx все расписано с диаграммами и понятно, даже с минимальным знанием английского... (см. режимы Read/Write Operations)

смысл в том, что при последовательном чтении, например, адрес задается только раз, а затем увеличивается автоматом при чтении след. ячейки ( ведущий отвечает SendAck(), а SendNoAck() выдается только при чтении последнего байта)...
Реклама
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

если бы я что то понимал в этих рисунках :))
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Сообщение uk8amk »

ChipKiller писал(а):программная работа ни чуть не медленнее, просто больше загрузка МК...
А вы точно работали с CodeVision? Данная либа заметно тормозит уже при скорости обращения выше 1-2КБайт/сек. Проверялось при частоте ядра 8МГц.
Но и это фигня по сравнению с данными комментариями:
kotriks писал(а): // USART Baud Rate: 1200   
kotriks писал(а):если бы я что то понимал в этих рисунках
Надо полагать, что приведенный вами исходник тоже представляет 'китайскую грамоту'?
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

uk8amk писал(а):А вы точно работали с CodeVision? Данная либа заметно тормозит уже при скорости обращения выше 1-2КБайт/сек
... с CodeVision работал, а библиотеками не пользуюсь - для реализации протокола достаточно написать 6 функций (тем более, что на сайте atmel все есть).

PS. ТС выложил "простыню" и предлагает поиграть в экстрасенсов...
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

может ссылочку дадите где копать? функция записи в еепром у меня очень простая

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

void write(unsigned char c1){ 
if (page_stop_status==1)  {
i2c_start(); 
i2c_write(0xa0);
i2c_write(addr>>8); 
i2c_write(addr & 0x00FF); 
page_stop_status=0;     }
 i2c_write(c1); 
 
addr++; 
pageSize++;  
if (pageSize==128) {
pageSize=0; 
page_stop();
 }   
}  
чтобы подсказать вам не нужен весь код, функция реализации записи и чтения с еепром я выложил полностью.
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

дока avr300 идет вместе с кодом примера
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

сделал так что то скорость не увеличилась

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

TWCR = (1<<TWEA)|(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT))) {};

TWDR = 0xa0;
TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT))) {};

TWDR = (temp_addr>>8);
TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT))) {};

TWDR = (temp_addr & 0x00FF);
TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT))) {};

for(cnt=0;cnt<128;cnt++)    {  
TWCR = (1<<TWEA)|(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT))) {};

TWDR = 0xA1;
TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT))) {};

TWCR = (1<<TWEA)|(1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))) {};
putchar(TWDR); 
 
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

забыл спросить ноги в twi можно выбирать или нет?
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

В железном I2C (TWI) ноги тоже железные и менять их нельзя.
А почему вам кажется что скорость маленькая? Прикиньте объем информации и тактовую частоту интерфейса, возможно что все работает как надо :idea: Я вот как-то записывал флеш на 2 мегабайта через UART на скорости 38400 - 10 минут, тоже думал медленно, а потом просчитал - все верно, быстрее и не получится :)))
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

Значит TWI мне не подойдёт потому что у меня уже готовые заказанные печатки. читал что есть 3 режима работы у l2c шины, стандарт, быстрый, и супер быстрый. в интернете не нашёл не одного примера работы с шиной хотябы до 400кило с сек. :(
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

kotriks писал(а):что есть 3 режима работы у l2c шины, стандарт, быстрый, и супер быстрый
...про супер быстрый не припомню (может отстал от жизни :)) ), стандарт - 100Kb, быстрый - 400. 100Kb пример выложен на сайте atmel еще под реализацию на at89c2051. Запись всегда значительно медленней.

PS. I2C вообще-то не славится супер скоростями, может стоит выбрать что-то другое...
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

на си бы не понимаю я этот асм )
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Сообщение uk8amk »

kotriks писал(а):что то скорость не увеличилась
Какая скорость UART, какая у TWI?
Если у вас UART действительно 1200бод, то поднять скорость.

Если UART и TWI на макисмуме, то хоть как-то убыстрить можно оптимизацией вашего алгоритма.
Вы написали:
kotriks писал(а):TWCR = (1<<TWEA)|(1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))) {};
putchar(TWDR);
Т.е:
1.Начать прием TWI
2.Ждать завершения приема TWI
3.Начать передачу UART
4.Ждать завершения передачи UART.

Видите, у вас подряд 2 задержки. Переделаем алгоритм так:
1.Прочитать TWI байт N
2.Начать чтение TWI байта N+1
3.Начать передачу в UART байта N
4.Ждать окончания передачи TWI и UART.
5.Goto п.1
.......
Передать последний оставшийся байт в UART.
End.
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

можно ли при скорости 9600 и фьюзами на 8 мгц с див8 выдавиь максимум? или див8 нужно будет убрать? просто для меня не желательно повышать частоту так как у меня потребление возрастёт, чего очень бы не хотелось.
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

нашёл тут скрипт для работы с TWI может тут что то лишнее

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

#define TWINT 128
#define TWSTA 32
#define TWSTO 16
#define TWEN  4 
#define TWEA  64
#define EEPROM_BUS_ADDRESS 0xa0

//Fuctions' prototypes
char ee_read(unsigned int);
char twi_read(char);
void twi_write(char);
void twi_start(void);
void twi_stop(void);     

char twi_read(char ACK)
{ 
                if(ACK) TWCR=TWINT|TWEA|TWEN;
                else TWCR=TWINT|TWEN;
                while(!(TWCR&(TWINT)));
                return TWDR;             
}
void twi_write(char data)
{                          
                TWDR=data;
                TWCR=TWINT|TWEN;
                while(!(TWCR&(TWINT)));
}   
void twi_start(void)
{
                TWCR=TWINT|TWSTA|TWEN;
                while(!(TWCR&(TWINT)));
}
void twi_stop(void)
{ 
                TWCR=TWINT|TWEN|TWSTO;
}
char ee_read(unsigned int adress)
{ 
                char data;
                twi_start();
                twi_write(EEPROM_BUS_ADDRESS);
                twi_write((unsigned char)(adress));
                twi_start();
                twi_write(EEPROM_BUS_ADDRESS|1);
                data=twi_read(0);
                twi_stop();
                return data;       
}                                        
void ee_write(unsigned int adress, unsigned char data)
{
   twi_start();
   twi_write(EEPROM_BUS_ADDRESS);
   twi_write(adress);
   twi_write(data);
   twi_stop();
   delay_ms(10);
}
ругается при компиле на

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

#define TWSTA 32
#define TWSTO 16
#define TWEN  4 
#define TWEA  64
для чего они вообще нужны?

я так понимаю для работы мне понадобятся только функции

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

//Fuctions' prototypes
char twi_read(char);
void twi_write(char);
void twi_start(void);
void twi_stop(void);     

char twi_read(char ACK)
{ 
                if(ACK) TWCR=TWINT|TWEA|TWEN;
                else TWCR=TWINT|TWEN;
                while(!(TWCR&(TWINT)));
                return TWDR;             
}
void twi_write(char data)
{                          
                TWDR=data;
                TWCR=TWINT|TWEN;
                while(!(TWCR&(TWINT)));
}   
void twi_start(void)
{
                TWCR=TWINT|TWSTA|TWEN;
                while(!(TWCR&(TWINT)));
}
void twi_stop(void)
{ 
                TWCR=TWINT|TWEN|TWSTO;
}
правильно?
Ответить

Вернуться в «Периферия»