|
AVR Studio 5 + avrlib + DS1307, Проблемы с I2C интерфейсом |
|
|
|
Sep 21 2011, 13:02
|
Группа: Участник
Сообщений: 11
Регистрация: 21-09-11
Пользователь №: 67 312

|
Друзья подскажите как обмениваться данными с часами DS1307 через функции avrlib Раньше писал с CodeVision там программный I2C и библиотека под часы была но пришлось перейти на AVR Studio так как библиотеки avrlib есть графический дисплей вот что то пытался написать но не работает не пойму как пользоваться I2C Библиотекой в итоге этого исходника ничего не происходит хотя импульсы на выходе контроллера есть (mega128) FCpu=8мгц В переменных нули =(((
i2cSetBitrate(50); i2cInit(); while(1) {
i2cSendStart(); _delay_ms(100); i2cSendByte(0xd0); _delay_ms(100); i2cSendByte(0); _delay_ms(100); i2cSendStart(); _delay_ms(100); i2cSendByte(0xd1); _delay_ms(100); sek= i2cGetReceivedByte(); min= i2cGetReceivedByte(); hour= i2cGetReceivedByte();
i2cSendStop();
|
|
|
|
|
Sep 22 2011, 03:07
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (Дима 128 @ Sep 21 2011, 22:02)  Друзья подскажите как обмениваться данными с часами DS1307 Уважаемый Дима 128, сообщество будет благодарно, если Вы будете соблюдать нормы русского языка. Например, расставлять знаки припинания  Без них, поверьте, понять смылс иной раз невозможно (Казнить нельзя помиловать). По теме: Вам следует почиать стандарт на шину I2C. Там описаны старт условия, стоп условия, когда необходимо подтвержать прием, когда нет. Как мне кажется, задержки в 100 мс - совершенно лишние. Аппаратный модуль TWI в микроконтроллере сделает все "сам". Успехов!
--------------------
Выбор.
|
|
|
|
|
Sep 22 2011, 04:16
|
Группа: Участник
Сообщений: 11
Регистрация: 21-09-11
Пользователь №: 67 312

|
По теме: Вам следует почиать стандарт на шину I2C. Там описаны старт условия, стоп условия, когда необходимо подтвержать прием, когда нет. Как мне кажется, задержки в 100 мс - совершенно лишние. Аппаратный модуль TWI в микроконтроллере сделает все "сам".
Успехов!
Ну эта задержка уже так для эксперимента =))) Я читал про модуль и на ассемблере его запускал но хотелось бы узнать как функцией avrlib пользоваться раз она там есть уж =)))
Или AVR Studio + avrlib не наш метод?
|
|
|
|
|
Sep 22 2011, 09:32
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (Дима 128 @ Sep 22 2011, 13:16)  Ну эта задержка уже так для эксперимента =))) Для какого эксперимента? Шина I2C до нескольких сотен килобит работает) QUOTE (Дима 128 @ Sep 22 2011, 13:16)  функцией avrlib пользоваться раз она там есть уж =))) У меня нет avrlib( Если речь об avrlibc из WinAVR, то не могу найти указанные функции. У меня WinAVR20071221. QUOTE (Дима 128 @ Sep 22 2011, 13:16)  Или AVR Studio + avrlib не наш метод? Да это-то тут при чем?  Используйте то, что Вам удобнее. Попробуйте посмотреть на форуме подобные темы.Народ не одну сотню DS1307 запустил))) Я тоже с ней работал, но это было давно ( 5 лет назад ). Исходников не осталось, к сожалению, иначе бы с удовольствием поделился бы)))
--------------------
Выбор.
|
|
|
|
|
Sep 22 2011, 15:48
|
Группа: Участник
Сообщений: 11
Регистрация: 21-09-11
Пользователь №: 67 312

|
Так вот и я запускал не одни часы =))) Но в CodeVision там вообще своя библиотека под них есть, но нет хорошей библиотеки для работы с графическим дисплеем, переписывать под CodeVision, avrlib библиотеку графического дисплея, еще хуже чем разобраться с функциями I2C Я просто не очень давно на си пишу и строчки длинные с математическими действиями над регистром меня ставят иногда в тупик =)))
|
|
|
|
|
Sep 22 2011, 18:01
|
Группа: Участник
Сообщений: 11
Регистрация: 21-09-11
Пользователь №: 67 312

|
Пробовал вот так rs&=3; if (sqwe) rs|=0x10; if (out) rs|=0x80; i2cSendStart(); i2cWaitForComplete(); i2cSendByte(0xd0); i2cWaitForComplete();
i2cSendByte(7); i2cWaitForComplete(); i2cSendByte(rs); i2cWaitForComplete(); i2cSendStop(); Инициализация
И прочитать
i2cSendStart(); i2cWaitForComplete(); i2cSendByte(0xd0); i2cWaitForComplete(); i2cSendByte(0); i2cWaitForComplete(); i2cSendStart(); i2cWaitForComplete(); i2cSendByte(0xd1); i2cWaitForComplete(); *sec=i2cGetReceivedByte(1); i2cWaitForComplete(); *min=i2cGetReceivedByte(1); i2cWaitForComplete(); *hour=i2cGetReceivedByte(0); i2cWaitForComplete(); i2cSendStop();
И не получается =)))
|
|
|
|
|
Sep 23 2011, 08:07
|
Группа: Участник
Сообщений: 11
Регистрация: 21-09-11
Пользователь №: 67 312

|
Ну не писать же библиотеку I2C С нуля если она там есть просто не совсем ясно как пользоваться ей =)))
|
|
|
|
|
Sep 23 2011, 11:47
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (Дима 128 @ Sep 23 2011, 17:07)  Ну не писать же библиотеку I2C С нуля если она там есть просто не совсем ясно как пользоваться ей =))) А чего там писать?  Аппаратный модуль сам все сделает. Почитайте документацию, придет понимание, потом и библиотеку прикрутите))) Вот писать программный I2C - это да, трудно! Хотя, если честно, тоже просто  Я где-то в прикрепленной теме (библиотеки полезных программ) лет 5 назад выкладывал библиотеку, которая и аппаратный TWI использует, и позволяет программно шину реализовать. Если же хочется использовать именно avrlib, то читайте документацию. Там все должно быть. Ну, а для полного понимания - спецификацию на шину I2C. Я уже Вам это советовал. Когда-то все равно придется это сделать.
--------------------
Выбор.
|
|
|
|
|
Sep 23 2011, 14:59
|
Группа: Участник
Сообщений: 11
Регистрация: 21-09-11
Пользователь №: 67 312

|
Да я на ассемблере запускал его соответственно знаком с этим но что в библиотеки сишной, трудно понять для меня =))
Неужели никто не использовал avrlib?
|
|
|
|
|
Sep 23 2011, 16:55
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(Дима 128 @ Sep 21 2011, 17:02)  i2cSendStart(); _delay_ms(100); i2cSendByte(0xd0); _delay_ms(100); i2cSendByte(0); _delay_ms(100); i2cSendStart(); _delay_ms(100); i2cSendByte(0xd1); _delay_ms(100); sek= i2cGetReceivedByte(); min= i2cGetReceivedByte(); hour= i2cGetReceivedByte();
i2cSendStop(); А вы пробовали проверить значение ACK бита которое отдает вам DS1307? Это дало бы какую то информацию. И неплохо знать что какой ACK вы отдаете при чтении. Еще вот что я думаю. После передачи D0, 00 вы передаете сразу старт условие. А может стоило бы сначала стоп передать?
|
|
|
|
|
Sep 23 2011, 18:30
|
Группа: Участник
Сообщений: 11
Регистрация: 21-09-11
Пользователь №: 67 312

|
Вы про бит чтения.запись? Там получается что у устройства адрес 1101000 семи разрядный + бит этот получается 11010000=0xd0 Я на основе примера из CodeVisin пытался сделать там часы работают
i2c_start(); i2c_write(0xd0); i2c_write(0); i2c_start(); i2c_write(0xd1); *sec=bcd2bin(i2c_read(1)); *min=bcd2bin(i2c_read(1)); *hour=bcd2bin(i2c_read(0)); i2c_stop();
А вот как это с функциями из avrlib это проделать не знаю что то упускаю пробовал вот так
i2cSetBitrate(100); i2cInit();
i2cSendStart();
i2cSendByte(0xD0);
i2cSendByte(0);
i2cSendStop();
i2cSendStart();
i2cSendByte(0xD1);
sek=i2cGetReceivedByte();
i2cSendStop();
Но где то ошибка есть =(((
Вот функции которые есть в avrlib
// functions
//! Initialize I2C (TWI) interface void i2cInit(void);
//! Set the I2C transaction bitrate (in KHz) void i2cSetBitrate(u16 bitrateKHz);
// I2C setup and configurations commands //! Set the local (AVR processor's) I2C device address void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn);
//! Set the user function which handles receiving (incoming) data as a slave void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData)); //! Set the user function which handles transmitting (outgoing) data as a slave void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData));
// Low-level I2C transaction commands //! Send an I2C start condition in Master mode void i2cSendStart(void); //! Send an I2C stop condition in Master mode void i2cSendStop(void); //! Wait for current I2C operation to complete void i2cWaitForComplete(void); //! Send an (address|R/W) combination or a data byte over I2C void i2cSendByte(u08 data); //! Receive a data byte over I2C // ackFlag = TRUE if recevied data should be ACK'ed // ackFlag = FALSE if recevied data should be NACK'ed void i2cReceiveByte(u08 ackFlag); //! Pick up the data that was received with i2cReceiveByte() u08 i2cGetReceivedByte(void); //! Get current I2c bus status from TWSR u08 i2cGetStatus(void);
// high-level I2C transaction commands
//! send I2C data to a device on the bus void i2cMasterSend(u08 deviceAddr, u08 length, u08 *data); //! receive I2C data from a device on the bus void i2cMasterReceive(u08 deviceAddr, u08 length, u08* data);
//! send I2C data to a device on the bus (non-interrupt based) u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data); //! receive I2C data from a device on the bus (non-interrupt based) u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data);
//! Get the current high-level state of the I2C interface eI2cStateType i2cGetState(void);
#endif
|
|
|
|
|
Sep 23 2011, 18:37
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(Дима 128 @ Sep 23 2011, 21:59)  Вы про бит чтения.запись? Там получается что у устройства адрес 1101000 семи разрядный + бит этот получается 11010000=0xd0 Нет, я про бит ACK, который идет после бита чтение-запись. Он 9-й по счету. Вам надо читать стандарт I2C, там это написано. И в ваших исходниках реализация этого бита не видна. Может даже ваш контроллер не формирует такт для него из за чего сбивается весь протокол.
|
|
|
|
|
Sep 23 2011, 18:47
|
Группа: Участник
Сообщений: 11
Регистрация: 21-09-11
Пользователь №: 67 312

|
Как же реализовать это в этих функциях? Я думал там это уже все есть =)))
|
|
|
|
|
Sep 24 2011, 06:52
|
Группа: Участник
Сообщений: 11
Регистрация: 21-09-11
Пользователь №: 67 312

|
Да наверно придется что то самому придумать =(((
|
|
|
|
|
Sep 25 2011, 16:27
|
Группа: Участник
Сообщений: 11
Регистрация: 21-09-11
Пользователь №: 67 312

|
Вот функции из сишного файла
#include <avr/io.h> #include <avr/interrupt.h>
#include "i2c.h"
#include "rprintf.h" // include printf function library #include "uart2.h"
// Standard I2C bit rates are: // 100KHz for slow speed // 400KHz for high speed
//#define I2C_DEBUG
// I2C state and address variables static volatile eI2cStateType I2cState; static u08 I2cDeviceAddrRW; // send/transmit buffer (outgoing data) static u08 I2cSendData[I2C_SEND_DATA_BUFFER_SIZE]; static u08 I2cSendDataIndex; static u08 I2cSendDataLength; // receive buffer (incoming data) static u08 I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE]; static u08 I2cReceiveDataIndex; static u08 I2cReceiveDataLength;
// function pointer to i2c receive routine //! I2cSlaveReceive is called when this processor // is addressed as a slave for writing static void (*i2cSlaveReceive)(u08 receiveDataLength, u08* recieveData); //! I2cSlaveTransmit is called when this processor // is addressed as a slave for reading static u08 (*i2cSlaveTransmit)(u08 transmitDataLengthMax, u08* transmitData);
// functions void i2cInit(void) { // set pull-up resistors on I2C bus pins // TODO: should #ifdef these sbi(PORTC, 0); // i2c SCL on ATmega163,323,16,32,etc sbi(PORTC, 1); // i2c SDA on ATmega163,323,16,32,etc sbi(PORTD, 0); // i2c SCL on ATmega128,64 sbi(PORTD, 1); // i2c SDA on ATmega128,64
// clear SlaveReceive and SlaveTransmit handler to null i2cSlaveReceive = 0; i2cSlaveTransmit = 0; // set i2c bit rate to 100KHz i2cSetBitrate(100); // enable TWI (two-wire interface) sbi(TWCR, TWEN); // set state I2cState = I2C_IDLE; // enable TWI interrupt and slave address ACK sbi(TWCR, TWIE); sbi(TWCR, TWEA); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); // enable interrupts sei(); }
void i2cSetBitrate(u16 bitrateKHz) { u08 bitrate_div; // set i2c bitrate // SCL freq = F_CPU/(16+2*TWBR)) #ifdef TWPS0 // for processors with additional bitrate division (mega128) // SCL freq = F_CPU/(16+2*TWBR*4^TWPS) // set TWPS to zero cbi(TWSR, TWPS0); cbi(TWSR, TWPS1); #endif // calculate bitrate division bitrate_div = ((F_CPU/1000l)/bitrateKHz); if(bitrate_div >= 16) bitrate_div = (bitrate_div-16)/2; outb(TWBR, bitrate_div); }
void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn) { // set local device address (used in slave mode only) outb(TWAR, ((deviceAddr&0xFE) | (genCallEn?1:0)) ); }
void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData)) { i2cSlaveReceive = i2cSlaveRx_func; }
void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData)) { i2cSlaveTransmit = i2cSlaveTx_func; }
inline void i2cSendStart(void) { // send start condition outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA)); }
inline void i2cSendStop(void) { // transmit stop condition // leave with TWEA on for slave receiving outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO)); }
inline void i2cWaitForComplete(void) { // wait for i2c interface to complete operation while( !(inb(TWCR) & BV(TWINT)) ); }
inline void i2cSendByte(u08 data) { // save data to the TWDR outb(TWDR, data); // begin send outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); }
inline void i2cReceiveByte(u08 ackFlag) { // begin receive over i2c if( ackFlag ) { // ackFlag = TRUE: ACK the recevied data outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); } else { // ackFlag = FALSE: NACK the recevied data outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); } }
inline u08 i2cGetReceivedByte(void) { // retieve received data byte from i2c TWDR return( inb(TWDR) ); }
inline u08 i2cGetStatus(void) { // retieve current i2c status from i2c TWSR return( inb(TWSR) ); }
void i2cMasterSend(u08 deviceAddr, u08 length, u08* data) { u08 i; // wait for interface to be ready while(I2cState); // set state I2cState = I2C_MASTER_TX; // save data I2cDeviceAddrRW = (deviceAddr & 0xFE); // RW cleared: write operation for(i=0; i<length; i++) I2cSendData[i] = *data++; I2cSendDataIndex = 0; I2cSendDataLength = length; // send start condition i2cSendStart(); }
void i2cMasterReceive(u08 deviceAddr, u08 length, u08* data) { u08 i; // wait for interface to be ready while(I2cState); // set state I2cState = I2C_MASTER_RX; // save data I2cDeviceAddrRW = (deviceAddr|0x01); // RW set: read operation I2cReceiveDataIndex = 0; I2cReceiveDataLength = length; // send start condition i2cSendStart(); // wait for data while(I2cState); // return data for(i=0; i<length; i++) *data++ = I2cReceiveData[i]; }
u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data) { u08 retval = I2C_OK;
// disable TWI interrupt cbi(TWCR, TWIE);
// send start condition i2cSendStart(); i2cWaitForComplete();
// send device address with write i2cSendByte( deviceAddr & 0xFE ); i2cWaitForComplete();
// check if device is present and live if( inb(TWSR) == TW_MT_SLA_ACK) { // send data while(length) { i2cSendByte( *data++ ); i2cWaitForComplete(); length--; } } else { // device did not ACK it's address, // data will not be transferred // return error retval = I2C_ERROR_NODEV; }
// transmit stop condition // leave with TWEA on for slave receiving i2cSendStop(); while( !(inb(TWCR) & BV(TWSTO)) );
// enable TWI interrupt sbi(TWCR, TWIE);
return retval; }
u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data) { u08 retval = I2C_OK;
// disable TWI interrupt cbi(TWCR, TWIE);
// send start condition i2cSendStart(); i2cWaitForComplete();
// send device address with read i2cSendByte( deviceAddr | 0x01 ); i2cWaitForComplete();
// check if device is present and live if( inb(TWSR) == TW_MR_SLA_ACK) { // accept receive data and ack it while(length > 1) { i2cReceiveByte(TRUE); i2cWaitForComplete(); *data++ = i2cGetReceivedByte(); // decrement length length--; }
// accept receive data and nack it (last-byte signal) i2cReceiveByte(FALSE); i2cWaitForComplete(); *data++ = i2cGetReceivedByte(); } else { // device did not ACK it's address, // data will not be transferred // return error retval = I2C_ERROR_NODEV; }
// transmit stop condition // leave with TWEA on for slave receiving i2cSendStop();
// enable TWI interrupt sbi(TWCR, TWIE);
return retval; } /* void i2cMasterTransferNI(u08 deviceAddr, u08 sendlength, u08* senddata, u08 receivelength, u08* receivedata) { // disable TWI interrupt cbi(TWCR, TWIE);
// send start condition i2cSendStart(); i2cWaitForComplete();
// if there's data to be sent, do it if(sendlength) { // send device address with write i2cSendByte( deviceAddr & 0xFE ); i2cWaitForComplete(); // send data while(sendlength) { i2cSendByte( *senddata++ ); i2cWaitForComplete(); sendlength--; } }
// if there's data to be received, do it if(receivelength) { // send repeated start condition i2cSendStart(); i2cWaitForComplete();
// send device address with read i2cSendByte( deviceAddr | 0x01 ); i2cWaitForComplete();
// accept receive data and ack it while(receivelength > 1) { i2cReceiveByte(TRUE); i2cWaitForComplete(); *receivedata++ = i2cGetReceivedByte(); // decrement length receivelength--; }
// accept receive data and nack it (last-byte signal) i2cReceiveByte(TRUE); i2cWaitForComplete(); *receivedata++ = i2cGetReceivedByte(); } // transmit stop condition // leave with TWEA on for slave receiving i2cSendStop(); while( !(inb(TWCR) & BV(TWSTO)) );
// enable TWI interrupt sbi(TWCR, TWIE); } */
//! I2C (TWI) interrupt service routine SIGNAL(SIG_2WIRE_SERIAL) { // read status bits u08 status = inb(TWSR) & TWSR_STATUS_MASK;
switch(status) { // Master General case TW_START: // 0x08: Sent start condition case TW_REP_START: // 0x10: Sent repeated start condition #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: M->START\r\n"); rprintfInit(uart1SendByte); #endif // send device address i2cSendByte(I2cDeviceAddrRW); break; // Master Transmitter & Receiver status codes case TW_MT_SLA_ACK: // 0x18: Slave address acknowledged case TW_MT_DATA_ACK: // 0x28: Data acknowledged #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MT->SLA_ACK or DATA_ACK\r\n"); rprintfInit(uart1SendByte); #endif if(I2cSendDataIndex < I2cSendDataLength) { // send data i2cSendByte( I2cSendData[I2cSendDataIndex++] ); } else { // transmit stop condition, enable SLA ACK i2cSendStop(); // set state I2cState = I2C_IDLE; } break; case TW_MR_DATA_NACK: // 0x58: Data received, NACK reply issued #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MR->DATA_NACK\r\n"); rprintfInit(uart1SendByte); #endif // store final received data byte I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR); // continue to transmit STOP condition case TW_MR_SLA_NACK: // 0x48: Slave address not acknowledged case TW_MT_SLA_NACK: // 0x20: Slave address not acknowledged case TW_MT_DATA_NACK: // 0x30: Data not acknowledged #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MTR->SLA_NACK or MT->DATA_NACK\r\n"); rprintfInit(uart1SendByte); #endif // transmit stop condition, enable SLA ACK i2cSendStop(); // set state I2cState = I2C_IDLE; break; case TW_MT_ARB_LOST: // 0x38: Bus arbitration lost //case TW_MR_ARB_LOST: // 0x38: Bus arbitration lost #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MT->ARB_LOST\r\n"); rprintfInit(uart1SendByte); #endif // release bus outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); // set state I2cState = I2C_IDLE; // release bus and transmit start when bus is free //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA)); break; case TW_MR_DATA_ACK: // 0x50: Data acknowledged #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MR->DATA_ACK\r\n"); rprintfInit(uart1SendByte); #endif // store received data byte I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR); // fall-through to see if more bytes will be received case TW_MR_SLA_ACK: // 0x40: Slave address acknowledged #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MR->SLA_ACK\r\n"); rprintfInit(uart1SendByte); #endif if(I2cReceiveDataIndex < (I2cReceiveDataLength-1)) // data byte will be received, reply with ACK (more bytes in transfer) i2cReceiveByte(TRUE); else // data byte will be received, reply with NACK (final byte in transfer) i2cReceiveByte(FALSE); break;
// Slave Receiver status codes case TW_SR_SLA_ACK: // 0x60: own SLA+W has been received, ACK has been returned case TW_SR_ARB_LOST_SLA_ACK: // 0x68: own SLA+W has been received, ACK has been returned case TW_SR_GCALL_ACK: // 0x70: GCA+W has been received, ACK has been returned case TW_SR_ARB_LOST_GCALL_ACK: // 0x78: GCA+W has been received, ACK has been returned #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: SR->SLA_ACK\r\n"); rprintfInit(uart1SendByte); #endif // we are being addressed as slave for writing (data will be received from master) // set state I2cState = I2C_SLAVE_RX; // prepare buffer I2cReceiveDataIndex = 0; // receive data byte and return ACK outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); break; case TW_SR_DATA_ACK: // 0x80: data byte has been received, ACK has been returned case TW_SR_GCALL_DATA_ACK: // 0x90: data byte has been received, ACK has been returned #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: SR->DATA_ACK\r\n"); rprintfInit(uart1SendByte); #endif // get previously received data byte I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR); // check receive buffer status if(I2cReceiveDataIndex < I2C_RECEIVE_DATA_BUFFER_SIZE) { // receive data byte and return ACK i2cReceiveByte(TRUE); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); } else { // receive data byte and return NACK i2cReceiveByte(FALSE); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); } break; case TW_SR_DATA_NACK: // 0x88: data byte has been received, NACK has been returned case TW_SR_GCALL_DATA_NACK: // 0x98: data byte has been received, NACK has been returned #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: SR->DATA_NACK\r\n"); rprintfInit(uart1SendByte); #endif // receive data byte and return NACK i2cReceiveByte(FALSE); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); break; case TW_SR_STOP: // 0xA0: STOP or REPEATED START has been received while addressed as slave #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: SR->SR_STOP\r\n"); rprintfInit(uart1SendByte); #endif // switch to SR mode with SLA ACK outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); // i2c receive is complete, call i2cSlaveReceive if(i2cSlaveReceive) i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData); // set state I2cState = I2C_IDLE; break;
// Slave Transmitter case TW_ST_SLA_ACK: // 0xA8: own SLA+R has been received, ACK has been returned case TW_ST_ARB_LOST_SLA_ACK: // 0xB0: GCA+R has been received, ACK has been returned #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: ST->SLA_ACK\r\n"); rprintfInit(uart1SendByte); #endif // we are being addressed as slave for reading (data must be transmitted back to master) // set state I2cState = I2C_SLAVE_TX; // request data from application if(i2cSlaveTransmit) I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData); // reset data index I2cSendDataIndex = 0; // fall-through to transmit first data byte case TW_ST_DATA_ACK: // 0xB8: data byte has been transmitted, ACK has been received #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: ST->DATA_ACK\r\n"); rprintfInit(uart1SendByte); #endif // transmit data byte outb(TWDR, I2cSendData[I2cSendDataIndex++]); if(I2cSendDataIndex < I2cSendDataLength) // expect ACK to data byte outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); else // expect NACK to data byte outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); break; case TW_ST_DATA_NACK: // 0xC0: data byte has been transmitted, NACK has been received case TW_ST_LAST_DATA: // 0xC8: #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: ST->DATA_NACK or LAST_DATA\r\n"); rprintfInit(uart1SendByte); #endif // all done // switch to open slave outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); // set state I2cState = I2C_IDLE; break;
// Misc case TW_NO_INFO: // 0xF8: No relevant state information // do nothing #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: NO_INFO\r\n"); rprintfInit(uart1SendByte); #endif break; case TW_BUS_ERROR: // 0x00: Bus error due to illegal start or stop condition #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: BUS_ERROR\r\n"); rprintfInit(uart1SendByte); #endif // reset internal hardware and release bus outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA)); // set state I2cState = I2C_IDLE; break; } }
eI2cStateType i2cGetState(void) { return I2cState; }
Вот функции из сишного файла
#include <avr/io.h> #include <avr/interrupt.h>
#include "i2c.h"
#include "rprintf.h" // include printf function library #include "uart2.h"
// Standard I2C bit rates are: // 100KHz for slow speed // 400KHz for high speed
//#define I2C_DEBUG
// I2C state and address variables static volatile eI2cStateType I2cState; static u08 I2cDeviceAddrRW; // send/transmit buffer (outgoing data) static u08 I2cSendData[I2C_SEND_DATA_BUFFER_SIZE]; static u08 I2cSendDataIndex; static u08 I2cSendDataLength; // receive buffer (incoming data) static u08 I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE]; static u08 I2cReceiveDataIndex; static u08 I2cReceiveDataLength;
// function pointer to i2c receive routine //! I2cSlaveReceive is called when this processor // is addressed as a slave for writing static void (*i2cSlaveReceive)(u08 receiveDataLength, u08* recieveData); //! I2cSlaveTransmit is called when this processor // is addressed as a slave for reading static u08 (*i2cSlaveTransmit)(u08 transmitDataLengthMax, u08* transmitData);
// functions void i2cInit(void) { // set pull-up resistors on I2C bus pins // TODO: should #ifdef these sbi(PORTC, 0); // i2c SCL on ATmega163,323,16,32,etc sbi(PORTC, 1); // i2c SDA on ATmega163,323,16,32,etc sbi(PORTD, 0); // i2c SCL on ATmega128,64 sbi(PORTD, 1); // i2c SDA on ATmega128,64
// clear SlaveReceive and SlaveTransmit handler to null i2cSlaveReceive = 0; i2cSlaveTransmit = 0; // set i2c bit rate to 100KHz i2cSetBitrate(100); // enable TWI (two-wire interface) sbi(TWCR, TWEN); // set state I2cState = I2C_IDLE; // enable TWI interrupt and slave address ACK sbi(TWCR, TWIE); sbi(TWCR, TWEA); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); // enable interrupts sei(); }
void i2cSetBitrate(u16 bitrateKHz) { u08 bitrate_div; // set i2c bitrate // SCL freq = F_CPU/(16+2*TWBR)) #ifdef TWPS0 // for processors with additional bitrate division (mega128) // SCL freq = F_CPU/(16+2*TWBR*4^TWPS) // set TWPS to zero cbi(TWSR, TWPS0); cbi(TWSR, TWPS1); #endif // calculate bitrate division bitrate_div = ((F_CPU/1000l)/bitrateKHz); if(bitrate_div >= 16) bitrate_div = (bitrate_div-16)/2; outb(TWBR, bitrate_div); }
void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn) { // set local device address (used in slave mode only) outb(TWAR, ((deviceAddr&0xFE) | (genCallEn?1:0)) ); }
void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData)) { i2cSlaveReceive = i2cSlaveRx_func; }
void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData)) { i2cSlaveTransmit = i2cSlaveTx_func; }
inline void i2cSendStart(void) { // send start condition outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA)); }
inline void i2cSendStop(void) { // transmit stop condition // leave with TWEA on for slave receiving outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO)); }
inline void i2cWaitForComplete(void) { // wait for i2c interface to complete operation while( !(inb(TWCR) & BV(TWINT)) ); }
inline void i2cSendByte(u08 data) { // save data to the TWDR outb(TWDR, data); // begin send outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); }
inline void i2cReceiveByte(u08 ackFlag) { // begin receive over i2c if( ackFlag ) { // ackFlag = TRUE: ACK the recevied data outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); } else { // ackFlag = FALSE: NACK the recevied data outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); } }
inline u08 i2cGetReceivedByte(void) { // retieve received data byte from i2c TWDR return( inb(TWDR) ); }
inline u08 i2cGetStatus(void) { // retieve current i2c status from i2c TWSR return( inb(TWSR) ); }
void i2cMasterSend(u08 deviceAddr, u08 length, u08* data) { u08 i; // wait for interface to be ready while(I2cState); // set state I2cState = I2C_MASTER_TX; // save data I2cDeviceAddrRW = (deviceAddr & 0xFE); // RW cleared: write operation for(i=0; i<length; i++) I2cSendData[i] = *data++; I2cSendDataIndex = 0; I2cSendDataLength = length; // send start condition i2cSendStart(); }
void i2cMasterReceive(u08 deviceAddr, u08 length, u08* data) { u08 i; // wait for interface to be ready while(I2cState); // set state I2cState = I2C_MASTER_RX; // save data I2cDeviceAddrRW = (deviceAddr|0x01); // RW set: read operation I2cReceiveDataIndex = 0; I2cReceiveDataLength = length; // send start condition i2cSendStart(); // wait for data while(I2cState); // return data for(i=0; i<length; i++) *data++ = I2cReceiveData[i]; }
u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data) { u08 retval = I2C_OK;
// disable TWI interrupt cbi(TWCR, TWIE);
// send start condition i2cSendStart(); i2cWaitForComplete();
// send device address with write i2cSendByte( deviceAddr & 0xFE ); i2cWaitForComplete();
// check if device is present and live if( inb(TWSR) == TW_MT_SLA_ACK) { // send data while(length) { i2cSendByte( *data++ ); i2cWaitForComplete(); length--; } } else { // device did not ACK it's address, // data will not be transferred // return error retval = I2C_ERROR_NODEV; }
// transmit stop condition // leave with TWEA on for slave receiving i2cSendStop(); while( !(inb(TWCR) & BV(TWSTO)) );
// enable TWI interrupt sbi(TWCR, TWIE);
return retval; }
u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data) { u08 retval = I2C_OK;
// disable TWI interrupt cbi(TWCR, TWIE);
// send start condition i2cSendStart(); i2cWaitForComplete();
// send device address with read i2cSendByte( deviceAddr | 0x01 ); i2cWaitForComplete();
// check if device is present and live if( inb(TWSR) == TW_MR_SLA_ACK) { // accept receive data and ack it while(length > 1) { i2cReceiveByte(TRUE); i2cWaitForComplete(); *data++ = i2cGetReceivedByte(); // decrement length length--; }
// accept receive data and nack it (last-byte signal) i2cReceiveByte(FALSE); i2cWaitForComplete(); *data++ = i2cGetReceivedByte(); } else { // device did not ACK it's address, // data will not be transferred // return error retval = I2C_ERROR_NODEV; }
// transmit stop condition // leave with TWEA on for slave receiving i2cSendStop();
// enable TWI interrupt sbi(TWCR, TWIE);
return retval; } /* void i2cMasterTransferNI(u08 deviceAddr, u08 sendlength, u08* senddata, u08 receivelength, u08* receivedata) { // disable TWI interrupt cbi(TWCR, TWIE);
// send start condition i2cSendStart(); i2cWaitForComplete();
// if there's data to be sent, do it if(sendlength) { // send device address with write i2cSendByte( deviceAddr & 0xFE ); i2cWaitForComplete(); // send data while(sendlength) { i2cSendByte( *senddata++ ); i2cWaitForComplete(); sendlength--; } }
// if there's data to be received, do it if(receivelength) { // send repeated start condition i2cSendStart(); i2cWaitForComplete();
// send device address with read i2cSendByte( deviceAddr | 0x01 ); i2cWaitForComplete();
// accept receive data and ack it while(receivelength > 1) { i2cReceiveByte(TRUE); i2cWaitForComplete(); *receivedata++ = i2cGetReceivedByte(); // decrement length receivelength--; }
// accept receive data and nack it (last-byte signal) i2cReceiveByte(TRUE); i2cWaitForComplete(); *receivedata++ = i2cGetReceivedByte(); } // transmit stop condition // leave with TWEA on for slave receiving i2cSendStop(); while( !(inb(TWCR) & BV(TWSTO)) );
// enable TWI interrupt sbi(TWCR, TWIE); } */
//! I2C (TWI) interrupt service routine SIGNAL(SIG_2WIRE_SERIAL) { // read status bits u08 status = inb(TWSR) & TWSR_STATUS_MASK;
switch(status) { // Master General case TW_START: // 0x08: Sent start condition case TW_REP_START: // 0x10: Sent repeated start condition #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: M->START\r\n"); rprintfInit(uart1SendByte); #endif // send device address i2cSendByte(I2cDeviceAddrRW); break; // Master Transmitter & Receiver status codes case TW_MT_SLA_ACK: // 0x18: Slave address acknowledged case TW_MT_DATA_ACK: // 0x28: Data acknowledged #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MT->SLA_ACK or DATA_ACK\r\n"); rprintfInit(uart1SendByte); #endif if(I2cSendDataIndex < I2cSendDataLength) { // send data i2cSendByte( I2cSendData[I2cSendDataIndex++] ); } else { // transmit stop condition, enable SLA ACK i2cSendStop(); // set state I2cState = I2C_IDLE; } break; case TW_MR_DATA_NACK: // 0x58: Data received, NACK reply issued #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MR->DATA_NACK\r\n"); rprintfInit(uart1SendByte); #endif // store final received data byte I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR); // continue to transmit STOP condition case TW_MR_SLA_NACK: // 0x48: Slave address not acknowledged case TW_MT_SLA_NACK: // 0x20: Slave address not acknowledged case TW_MT_DATA_NACK: // 0x30: Data not acknowledged #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MTR->SLA_NACK or MT->DATA_NACK\r\n"); rprintfInit(uart1SendByte); #endif // transmit stop condition, enable SLA ACK i2cSendStop(); // set state I2cState = I2C_IDLE; break; case TW_MT_ARB_LOST: // 0x38: Bus arbitration lost //case TW_MR_ARB_LOST: // 0x38: Bus arbitration lost #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MT->ARB_LOST\r\n"); rprintfInit(uart1SendByte); #endif // release bus outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); // set state I2cState = I2C_IDLE; // release bus and transmit start when bus is free //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA)); break; case TW_MR_DATA_ACK: // 0x50: Data acknowledged #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MR->DATA_ACK\r\n"); rprintfInit(uart1SendByte); #endif // store received data byte I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR); // fall-through to see if more bytes will be received case TW_MR_SLA_ACK: // 0x40: Slave address acknowledged #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: MR->SLA_ACK\r\n"); rprintfInit(uart1SendByte); #endif if(I2cReceiveDataIndex < (I2cReceiveDataLength-1)) // data byte will be received, reply with ACK (more bytes in transfer) i2cReceiveByte(TRUE); else // data byte will be received, reply with NACK (final byte in transfer) i2cReceiveByte(FALSE); break;
// Slave Receiver status codes case TW_SR_SLA_ACK: // 0x60: own SLA+W has been received, ACK has been returned case TW_SR_ARB_LOST_SLA_ACK: // 0x68: own SLA+W has been received, ACK has been returned case TW_SR_GCALL_ACK: // 0x70: GCA+W has been received, ACK has been returned case TW_SR_ARB_LOST_GCALL_ACK: // 0x78: GCA+W has been received, ACK has been returned #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: SR->SLA_ACK\r\n"); rprintfInit(uart1SendByte); #endif // we are being addressed as slave for writing (data will be received from master) // set state I2cState = I2C_SLAVE_RX; // prepare buffer I2cReceiveDataIndex = 0; // receive data byte and return ACK outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); break; case TW_SR_DATA_ACK: // 0x80: data byte has been received, ACK has been returned case TW_SR_GCALL_DATA_ACK: // 0x90: data byte has been received, ACK has been returned #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: SR->DATA_ACK\r\n"); rprintfInit(uart1SendByte); #endif // get previously received data byte I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR); // check receive buffer status if(I2cReceiveDataIndex < I2C_RECEIVE_DATA_BUFFER_SIZE) { // receive data byte and return ACK i2cReceiveByte(TRUE); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); } else { // receive data byte and return NACK i2cReceiveByte(FALSE); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); } break; case TW_SR_DATA_NACK: // 0x88: data byte has been received, NACK has been returned case TW_SR_GCALL_DATA_NACK: // 0x98: data byte has been received, NACK has been returned #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: SR->DATA_NACK\r\n"); rprintfInit(uart1SendByte); #endif // receive data byte and return NACK i2cReceiveByte(FALSE); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); break; case TW_SR_STOP: // 0xA0: STOP or REPEATED START has been received while addressed as slave #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: SR->SR_STOP\r\n"); rprintfInit(uart1SendByte); #endif // switch to SR mode with SLA ACK outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); // i2c receive is complete, call i2cSlaveReceive if(i2cSlaveReceive) i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData); // set state I2cState = I2C_IDLE; break;
// Slave Transmitter case TW_ST_SLA_ACK: // 0xA8: own SLA+R has been received, ACK has been returned case TW_ST_ARB_LOST_SLA_ACK: // 0xB0: GCA+R has been received, ACK has been returned #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: ST->SLA_ACK\r\n"); rprintfInit(uart1SendByte); #endif // we are being addressed as slave for reading (data must be transmitted back to master) // set state I2cState = I2C_SLAVE_TX; // request data from application if(i2cSlaveTransmit) I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData); // reset data index I2cSendDataIndex = 0; // fall-through to transmit first data byte case TW_ST_DATA_ACK: // 0xB8: data byte has been transmitted, ACK has been received #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: ST->DATA_ACK\r\n"); rprintfInit(uart1SendByte); #endif // transmit data byte outb(TWDR, I2cSendData[I2cSendDataIndex++]); if(I2cSendDataIndex < I2cSendDataLength) // expect ACK to data byte outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); else // expect NACK to data byte outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); break; case TW_ST_DATA_NACK: // 0xC0: data byte has been transmitted, NACK has been received case TW_ST_LAST_DATA: // 0xC8: #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: ST->DATA_NACK or LAST_DATA\r\n"); rprintfInit(uart1SendByte); #endif // all done // switch to open slave outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); // set state I2cState = I2C_IDLE; break;
// Misc case TW_NO_INFO: // 0xF8: No relevant state information // do nothing #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: NO_INFO\r\n"); rprintfInit(uart1SendByte); #endif break; case TW_BUS_ERROR: // 0x00: Bus error due to illegal start or stop condition #ifdef I2C_DEBUG rprintfInit(uart1AddToTxBuffer); rprintf("I2C: BUS_ERROR\r\n"); rprintfInit(uart1SendByte); #endif // reset internal hardware and release bus outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA)); // set state I2cState = I2C_IDLE; break; } }
eI2cStateType i2cGetState(void) { return I2cState; }
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|