singlskv 0 8 сентября, 2011 Опубликовано 8 сентября, 2011 · Жалоба Они практически в полном составе унаследованы от SAM7, разве что убрали наиболее одиозные глюки и добавили PDC. Идеология, однако, осталась прежней: мастер синхронного интерфейса у них может вылететь в overrun/underrun. Мое общение с TWI на SAM3 закончилось довольно быстро. Сдуру был написан честный драйвер с PDC и прерываниями, однако на тестировании выяснилось, что из 10 слейвов в составе устройства отзываются 8. Два AD9887 принципиально не дают ACK после адреса. Памятуя безблагодатные пляски с бубном при аналогичных симптомах на SAM7, не стал даже разбираться в причинах сего явления и просто откатился на bit-band. Если не сложно, покажите запуск PDC для I2C, не могу понять как его стартовать в различных вариантах: -запись от мастера слейву -чтение от слейва ну или полный драйвер запостите с PDC если запостите полный драйвер, обещаю опубликовать свое решение, если конечно выгорит..., ну и как бонус могу опубликовать решение для SAM7. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 8 сентября, 2011 Опубликовано 8 сентября, 2011 · Жалоба ну или полный драйвер запостите с PDC Держите. Но только совершенный as is, никаких комментариев не будет - наелся я уже атмеловского TWI и слышать о нем больше не хочу. iic.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 8 сентября, 2011 Опубликовано 8 сентября, 2011 · Жалоба [/quote name=aaarrr' date='Sep 8 2011, 21:45' post='970432] Держите. Но только совершенный as is, никаких комментариев не будет - наелся я уже атмеловского TWI и слышать о нем больше не хочу. iic.rar //------------------------------------------------------------------------------ static void I2cISR(void) __attribute__ ((interrupt ("IRQ"))); // I2C #define I2C_SEND_BUFF_LENGTH 2 #define I2C_RECV_BUFF_LENGTH 8 #define I2C_MEGA_ADDR 0xB2 // адрес меги на шине i2c enum { I2C_STATE_FREE = 0, I2C_STATE_SEND, I2C_STATE_RECEIVE, I2C_STATE_RECEIVED }; //------------------------------------------------------------------------------ // DWORD I2cSetSpeed(DWORD baud) // Установка скорости уарта // Input: // baud - скорость i2c // Output: реальная скорость уарта //---- DWORD I2cSetSpeed(DWORD baud) { int div, ckdiv, chdiv, cldiv; div = MCK_FREQUENCY / baud; div -= 6; // const ckdiv = 0; while (div > 510) { ckdiv++; if (ckdiv >= 8) return 0; div >>= 1; } chdiv = div >> 1; cldiv = div - chdiv; TWI_IDR = 0xFFFFFFFF; AIC_ICCR = (1 << TWI_ID); TWI_CR = TWI_CR_SWRST; TWI_CR = TWI_CR_MSEN; TWI_CWGR = (ckdiv << 16) | (chdiv << 8) | cldiv; return baud; } typedef struct { DWORD State; DWORD Index; DWORD MessageLength; BYTE OutBuff[i2C_SEND_BUFF_LENGTH]; BYTE InBuff[i2C_RECV_BUFF_LENGTH]; } Mega; Mega mega; BYTE Do_ticks; DWORD Do_state; DWORD Di_time; DWORD Di_cnt[6]; WORD DiLastFiltrWidth[5]; // размер окна фильтрации WORD DiFiltrCounter[5]; // счетчик фильтра DWORD SecondCounter; void SysTimerHandler() { DWORD tmp, i, bit; static DWORD StateTimeout; if (++SecondCounter >= 1000) { SecondCounter = 0; base.WorkingTime++; TimeFromStart++; } .................. if (mega.State != I2C_STATE_RECEIVED) StateTimeout++; else StateTimeout = 0; if (StateTimeout >= 2) { StateTimeout = 0; TWI_IDR = 0xFFFFFFFF; TWI_CR = TWI_CR_MSDIS; PMC_PCDR = (1 << TWI_ID); PIOA_PER = BIT1; PIOA_OER = BIT1; for (i = 0; i < 9; i++) { PIOA_SODR = BIT1; asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop"); PIOA_CODR = BIT1; asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop"); } PIOA_SODR = BIT1; PIOA_ODR = BIT1; PIOA_PDR = BIT1; PMC_PCER = (1 << TWI_ID); I2cSetSpeed(140000); mega.State = I2C_STATE_FREE; } switch (mega.State) { case I2C_STATE_RECEIVED: ............ TWI_MMR = ((I2C_MEGA_ADDR >> 1) << 16); TWI_THR = mega.OutBuff[0]; TWI_CR = TWI_CR_STOP; TWI_IER = TWI_IER_TXRDY | TWI_IER_TXCOMP; break; } case I2C_STATE_FREE: if (mega.State == I2C_STATE_FREE) DI &= ~BIT7; // нет связи с мегой mega.State = I2C_STATE_SEND; mega.Index = 0; ........... TWI_MMR = ((I2C_MEGA_ADDR >> 1) << 16); TWI_THR = mega.OutBuff[0]; TWI_CR = TWI_CR_STOP; TWI_IER = TWI_IER_TXRDY | TWI_IER_TXCOMP; break; } ........................... } //------------------------------------------------------------------------------ // static void I2cISR(void) // Обработчик прерывания I2C //---- static void I2cISR(void) { DWORD sr; AIC_IVR = 0; sr = TWI_SR; if (mega.State == I2C_STATE_SEND) { if (sr & TWI_SR_TXRDY) { mega.Index++; TWI_THR = mega.OutBuff[1]; TWI_IDR = 0xFFFFFFFF; TWI_IER = TWI_IER_TXCOMP; } if (sr & TWI_SR_TXCOMP) { if ((sr & TWI_SR_NACK) || (mega.Index == 0)) { TWI_IDR = 0xFFFFFFFF; mega.State = I2C_STATE_FREE; } else { mega.State = I2C_STATE_RECEIVE; mega.MessageLength = I2C_RECV_BUFF_LENGTH; mega.Index = 0; TWI_MMR = ((I2C_MEGA_ADDR >> 1) << 16) | TWI_MMR_MREAD; TWI_RHR; TWI_CR = TWI_CR_START; TWI_IDR = 0xFFFFFFFF; TWI_IER = TWI_IER_TXCOMP | TWI_IER_RXRDY; } } } else if (mega.State == I2C_STATE_RECEIVE) { if (sr & TWI_SR_RXRDY) { mega.InBuff[mega.Index] = TWI_RHR; mega.Index++; if (mega.Index == (I2C_RECV_BUFF_LENGTH - 1)) { TWI_CR = TWI_CR_STOP; } else if (mega.Index == I2C_RECV_BUFF_LENGTH) { TWI_IDR = 0xFFFFFFFF; mega.State = I2C_STATE_RECEIVED; } } else if (sr & TWI_SR_TXCOMP) { TWI_IDR = 0xFFFFFFFF; mega.State = I2C_STATE_RECEIVED; } } else { TWI_IDR = 0xFFFFFFFF; mega.State = I2C_STATE_FREE; TWI_RHR; } AIC_EOICR = 0; } вот как и обещал, пример для SAM7 драйвера у мну нет как такового нет, но кто в теме поймет... если стер что лишнее, телеграфируйте... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться