Например TDA7294

Форум РадиоКот • Просмотр темы - TWI библиотека c прерываниями, зависаем на СТАРТе
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Вт сен 30, 2025 11:25:54

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 3 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: TWI библиотека c прерываниями, зависаем на СТАРТе
СообщениеДобавлено: Вс сен 07, 2025 21:41:22 
Встал на лапы

Зарегистрирован: Пт мар 19, 2021 08:58:45
Сообщений: 120
Рейтинг сообщения: 0
Всем привет! Решил использовать библиотеку с прерываниями, всял с chipenable.ru использую на atmega328p.
twi_master.c
Спойлер
Код:
#include <avr/io.h>
#include <avr/interrupt.h>
#include "twi_master.h"

static unsigned char TWI_buf[ TWI_BUFFER_SIZE ];    // Transceiver buffer
static unsigned char TWI_msgSize;                   // Number of bytes to be transmitted.
static unsigned char TWI_state = TWI_NO_STATE;      // State byte. Default set to TWI_NO_STATE.

union TWI_statusReg TWI_statusReg = {0};            // TWI_statusReg is defined in TWI_Master.h

/****************************************************************************
Call this function to set up the TWI master to its initial standby state.
Remember to enable interrupts from the main application after initializing the TWI.
****************************************************************************/
void TWI_Master_Initialise(void)
{
   TWSR = TWI_TWPS;                        // Not used. Driver presumes prescaler to be 00.
   TWBR = TWI_TWBR;                           // Set bit rate register (Baudrate). Defined in header file.
   TWDR = 0xFF;                             // Default content = SDA released.
   TWCR = 0x00;
    TWCR = (1<<TWEN)|                          // Enable TWI-interface and release TWI pins.
    (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt.
    (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests.
    (0<<TWWC);                                 //
   
}

/****************************************************************************
Call this function to test if the TWI_ISR is busy transmitting.
****************************************************************************/
static void/*unsigned char*/ TWI_Transceiver_Busy( void )
{
   //return ( TWCR & (1<<TWIE) );               // IF TWI Interrupt is enabled then the Transceiver is busy
   while (TWCR & (1<<TWIE));    
}

/****************************************************************************
Call this function to fetch the state information of the previous operation. The function will hold execution (loop)
until the TWI_ISR has completed with the previous operation. If there was an error, then the function
will return the TWI State code.
****************************************************************************/
unsigned char TWI_Get_State_Info( void )
{
   TWI_Transceiver_Busy();          // Wait until TWI has completed the transmission.
   return ( TWI_state );                      // Return error state.
}

/****************************************************************************
Call this function to send a prepared message. The first byte must contain the slave address and the
read/write bit. Consecutive bytes contain the data to be sent, or empty locations for data to be read
from the slave. Also include how many bytes that should be sent/read including the address byte.
The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,
then initialize the next operation and return.
****************************************************************************/
void TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize )
{
   unsigned char temp;

   TWI_Transceiver_Busy();             // Wait until TWI is ready for next transmission.

   TWI_msgSize = msgSize;                        // Number of data to transmit.
   TWI_buf[0]  = msg[0];                         // Store slave address with R/W setting.
   
   if ( !( msg[0] & (TRUE << TWI_READ_BIT)) )       // If it is a write operation, then also copy data.
   {
      for ( temp = 1; temp < msgSize; temp++ )
      TWI_buf[ temp ] = msg[ temp ];
   }
   TWI_statusReg.all = 0;
   TWI_state         = TWI_NO_STATE ;
      
   TWCR = (1<<TWEN)|                      // TWI Interface enabled.
   (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.
   (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.
   (0<<TWWC);                             //
}

/****************************************************************************
Call this function to resend the last message. The driver will reuse the data previously put in the transceiver buffers.
The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,
then initialize the next operation and return.
****************************************************************************/
void TWI_Start_Transceiver( void )
{
   TWI_Transceiver_Busy();             // Wait until TWI is ready for next transmission.
   TWI_statusReg.all = 0;
   TWI_state         = TWI_NO_STATE;   
   TWCR = (1<<TWEN)|                             // TWI Interface enabled.
   (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.
   (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.
   (0<<TWWC);                             //
}

/****************************************************************************
Call this function to read out the requested data from the TWI transceiver buffer. I.e. first call
TWI_Start_Transceiver to send a request for data to the slave. Then Run this function to collect the
data when they have arrived. Include a pointer to where to place the data and the number of bytes
requested (including the address field) in the function call. The function will hold execution (loop)
until the TWI_ISR has completed with the previous operation, before reading out the data and returning.
If there was an error in the previous transmission the function will return the TWI error code.
****************************************************************************/
unsigned char TWI_Get_Data_From_Transceiver( unsigned char *msg, unsigned char msgSize )
{
   unsigned char i;

   TWI_Transceiver_Busy();             // Wait until TWI is ready for next transmission.

   if( TWI_statusReg.lastTransOK )               // Last transmission competed successfully.
   {
      for ( i = 0; i < msgSize; i++ )                 // Copy data from Transceiver buffer.
      {
         msg[ i ] = TWI_buf[ i ];
      }
   }
   return( TWI_statusReg.lastTransOK );
}

// ********** Interrupt Handlers ********** //

//This function is the Interrupt Service Routine (ISR), and called when the TWI interrupt is triggered;
//that is whenever a TWI event has occurred. This function should not be called directly from the main
//application.
ISR (TWI_vect) {
   static unsigned char TWI_bufPtr;
   
   switch (TWSR)
   {
      case TWI_START:             // START has been transmitted
      
      case TWI_REP_START:         // Repeated START has been transmitted
         TWI_bufPtr = 0;         // Set buffer pointer to the TWI Address location
         
      case TWI_MTX_ADR_ACK:       // SLA+W has been tramsmitted and ACK received
      
      case TWI_MTX_DATA_ACK:      // Data byte has been tramsmitted and ACK received
         if (TWI_bufPtr < TWI_msgSize)
         {
            TWDR = TWI_buf[TWI_bufPtr++];
            TWCR = (1<<TWEN)|                          // TWI Interface enabled
            (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to send byte
            (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           //
            (0<<TWWC);                                 //
         } else {                   // Send STOP after last byte
            TWI_statusReg.lastTransOK = TRUE;          // Set status bits to completed successfully.
            TWCR = (1<<TWEN)|                          // TWI Interface enabled
            (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
            (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
            (0<<TWWC);                                 //
         }
      break;
      
      case TWI_MRX_DATA_ACK:      // Data byte has been received and ACK tramsmitted
         TWI_buf[TWI_bufPtr++] = TWDR;
         
      case TWI_MRX_ADR_ACK:       // SLA+R has been tramsmitted and ACK received
         if (TWI_bufPtr < (TWI_msgSize-1) )             // Detect the last byte to NACK it.
         {
            TWCR = (1<<TWEN)|                          // TWI Interface enabled
            (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
            (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send ACK after reception
            (0<<TWWC);                                 //
         } else {                   // Send NACK after next reception      
            TWCR = (1<<TWEN)|                          // TWI Interface enabled
            (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
            (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send NACK after reception
            (0<<TWWC);                                 //
         }
      break;
      
      case TWI_MRX_DATA_NACK:     // Data byte has been received and NACK tramsmitted
         TWI_buf[TWI_bufPtr] = TWDR;
         TWI_statusReg.lastTransOK = TRUE;          // Set status bits to completed successfully.
         TWCR = (1<<TWEN)|                          // TWI Interface enabled
         (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
         (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
         (0<<TWWC);                                 //
      break;
      
      case TWI_ARB_LOST:          // Arbitration lost   
         TWCR = (1<<TWEN)|                          // TWI Interface enabled
         (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag
         (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|           // Initiate a (RE)START condition.
         (0<<TWWC);                                 //
      break;
      
      case TWI_MTX_ADR_NACK:      // SLA+W has been tramsmitted and NACK received
      
      case TWI_MRX_ADR_NACK:      // SLA+R has been tramsmitted and NACK received
      
      case TWI_MTX_DATA_NACK:     // Data byte has been tramsmitted and NACK received
      
//       case TWI_NO_STATE         // No relevant state information available; TWINT = “0”

      case TWI_BUS_ERROR:         // Bus error due to an illegal START or STOP condition
      
      default:
         TWI_state = TWSR;                          // Store TWSR and automatically sets clears noErrors bit.
         // Reset TWI Interface      
         TWCR = (1<<TWEN)|                          // Enable TWI-interface and release TWI pins
         (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt
         (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests
         (0<<TWWC);                                 //
      break;
   }
}

twi_master.h
Спойлер
Код:
#ifndef TWI_MASTER_H_
#define TWI_MASTER_H_

/****************************************************************************
  TWI Status/Control register definitions
****************************************************************************/
#define TWI_BUFFER_SIZE 4   // Set this to the largest message size that will be sent including address byte.

#define TWI_TWBR            0x0C        // TWI Bit rate Register setting.
                                        // Se Application note for detailed
                                        // information on setting this value.
// Not used defines!
#define TWI_TWPS          0x00        // This driver presumes prescaler = 00

/****************************************************************************
  Global definitions
****************************************************************************/

union TWI_statusReg                       // Status byte holding flags.
{
    unsigned char all;
    struct
    {
        unsigned char lastTransOK:1;     
        unsigned char unusedBits:7;
    };
};

extern union TWI_statusReg TWI_statusReg;

/****************************************************************************
  Bit and byte definitions
****************************************************************************/
#define TWI_READ_BIT  0       // Bit position for R/W bit in "address byte".
#define TWI_ADR_BITS  1       // Bit position for LSB of the slave address bits in the init byte.

#define TRUE          1
#define FALSE         0

/****************************************************************************
  TWI State codes
****************************************************************************/
// General TWI Master staus codes                     
#define TWI_START                  0x08  // START has been transmitted 
#define TWI_REP_START              0x10  // Repeated START has been transmitted
#define TWI_ARB_LOST               0x38  // Arbitration lost

// TWI Master Transmitter staus codes                     
#define TWI_MTX_ADR_ACK            0x18  // SLA+W has been tramsmitted and ACK received
#define TWI_MTX_ADR_NACK           0x20  // SLA+W has been tramsmitted and NACK received
#define TWI_MTX_DATA_ACK           0x28  // Data byte has been tramsmitted and ACK received
#define TWI_MTX_DATA_NACK          0x30  // Data byte has been tramsmitted and NACK received

// TWI Master Receiver staus codes 
#define TWI_MRX_ADR_ACK            0x40  // SLA+R has been tramsmitted and ACK received
#define TWI_MRX_ADR_NACK           0x48  // SLA+R has been tramsmitted and NACK received
#define TWI_MRX_DATA_ACK           0x50  // Data byte has been received and ACK tramsmitted
#define TWI_MRX_DATA_NACK          0x58  // Data byte has been received and NACK tramsmitted

// TWI Slave Transmitter staus codes
#define TWI_STX_ADR_ACK            0xA8  // Own SLA+R has been received; ACK has been returned
#define TWI_STX_ADR_ACK_M_ARB_LOST 0xB0  // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned
#define TWI_STX_DATA_ACK           0xB8  // Data byte in TWDR has been transmitted; ACK has been received
#define TWI_STX_DATA_NACK          0xC0  // Data byte in TWDR has been transmitted; NOT ACK has been received
#define TWI_STX_DATA_ACK_LAST_BYTE 0xC8  // Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received

// TWI Slave Receiver staus codes
#define TWI_SRX_ADR_ACK            0x60  // Own SLA+W has been received ACK has been returned
#define TWI_SRX_ADR_ACK_M_ARB_LOST 0x68  // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned
#define TWI_SRX_GEN_ACK            0x70  // General call address has been received; ACK has been returned
#define TWI_SRX_GEN_ACK_M_ARB_LOST 0x78  // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_ACK       0x80  // Previously addressed with own SLA+W; data has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_NACK      0x88  // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
#define TWI_SRX_GEN_DATA_ACK       0x90  // Previously addressed with general call; data has been received; ACK has been returned
#define TWI_SRX_GEN_DATA_NACK      0x98  // Previously addressed with general call; data has been received; NOT ACK has been returned
#define TWI_SRX_STOP_RESTART       0xA0  // A STOP condition or repeated START condition has been received while still addressed as Slave

// TWI Miscellaneous status codes
#define TWI_NO_STATE               0xF8  // No relevant state information available; TWINT = “0”
#define TWI_BUS_ERROR              0x00  // Bus error due to an illegal START or STOP condition


// Sample TWI transmission commands
#define TWI_CMD_MASTER_WRITE 0x10
#define TWI_CMD_MASTER_READ  0x20

// Sample TWI transmission states, used in the main application.
#define SEND_DATA             0x01
#define REQUEST_DATA          0x02
#define READ_DATA_FROM_BUFFER 0x03

/****************************************************************************
  Function definitions
****************************************************************************/
void TWI_Master_Initialise(void);
static void /*unsigned char*/ TWI_Transceiver_Busy(void);
unsigned char TWI_Get_State_Info(void);
void TWI_Start_Transceiver_With_Data(unsigned char * , unsigned char);
void TWI_Start_Transceiver(void);
unsigned char TWI_Get_Data_From_Transceiver(unsigned char *, unsigned char);

#endif /* TWI_MASTER_H_ */

В итоге не могу понять почему я висну при СТАРЕ передачи адреса ведомого устройства и бит чтения/записи + байт данных. Пытаю все это дело в протусе, нужно запустить дисплей 1602+PCF8574. Начал с инициализации дисплея, в старндартной функции библиотеки дисплея дописал следующее:
Код:
void lq_transmitI2C(LiquidCrystalDevice_t* device, uint8_t value)
{
//    i2c_master_sendByte(device->Address, value | device->Backlight); //Ранее было так
   messageBuf[0] = ( device->Address << TWI_ADR_BITS ) | ( FALSE << TWI_READ_BIT ); // адрес ведомого + бит записи
   messageBuf[1] = ( value | device->Backlight ); // данные
   TWI_Start_Transceiver_With_Data( messageBuf, 2 );
};


Подозрения падают у меня на вот эту функцию в библиотеке TWI:
Код:
static void/*unsigned char*/ TWI_Transceiver_Busy( void )
{
   //return ( TWCR & (1<<TWIE) );               // IF TWI Interrupt is enabled then the Transceiver is busy
   while (TWCR & (1<<TWIE));    
}

При старте и последующем зависании в регистре присутсвует такое значение TWSR 0x08 - что говорит о передача данных только началась, и линии SCL и SDA притянуты к земле. Т.е. получается нет зависаем, а ждем пока когда TWI модуль освободится, только от чего он освобждается?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: TWI библиотека c прерываниями, зависаем на СТАРТе
СообщениеДобавлено: Вт сен 09, 2025 06:19:26 
Прорезались зубы

Карма: -10
Рейтинг сообщений: -20
Зарегистрирован: Пн окт 04, 2010 11:55:41
Сообщений: 226
Рейтинг сообщения: 0
.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: TWI библиотека c прерываниями, зависаем на СТАРТе
СообщениеДобавлено: Вт сен 09, 2025 19:17:34 
Встал на лапы

Зарегистрирован: Пт мар 19, 2021 08:58:45
Сообщений: 120
Рейтинг сообщения: 0
Частично решил свои проблемы:
1.Невнимательность, запускал инициализацию дисплея или вот такой код для проверки отправки что выдаст
Код:
   messageBuf[0] = ( 0x27 << TWI_ADR_BITS ) | ( FALSE << TWI_READ_BIT ); // адрес ведомого + бит записи
   messageBuf[1] =0x10; // данные
   TWI_Start_Transceiver_With_Data( messageBuf, 2 )

после иициализации настроек TWI модуля, НО перед разрешение прерываний sei();
2. Порты линий SCL и SDA не были подтянуты к питанию, перенастроил.
3. Убрал пока эту функцию
Код:
static void/*unsigned char*/ TWI_Transceiver_Busy( void )
{
   //return ( TWCR & (1<<TWIE) );               // IF TWI Interrupt is enabled then the Transceiver is busy
   while (TWCR & (1<<TWIE));   
}
из библиотеки TWI.

Теперь если шлю кусок кода тот,что выше написал - то норм отрабатывает, SDA и SCL в высоком уровне, отправка Адреса+W+Data и опять в высоком уровне. В протусе в I2C debugger тоже все красиво - S 4E A 10 A P, при условии что адресс указан 0х27.
Но как только вставляю в библиотеку дисплея
Код:
void lq_transmitI2C(LiquidCrystalDevice_t* device, uint8_t value)
{
//    i2c_master_sendByte(device->Address, value | device->Backlight); //Ранее было так
   messageBuf[0] = ( device->Address << TWI_ADR_BITS ) | ( FALSE << TWI_READ_BIT ); // адрес ведомого + бит записи
   messageBuf[1] = ( value | device->Backlight ); // данные
   TWI_Start_Transceiver_With_Data( messageBuf, 2 );
};
начинаю инициализацию дисплея, то почему-то после S добовляетя еще Sr и все полетело к х.... Смотрю, а между отправками у меня опять низкий уровень((((

Ищем далее... пишу тестотправку, не одну, а две через 100мкрС.
Код:
 messageBuf[0] = ( 0x27 << TWI_ADR_BITS ) | ( FALSE << TWI_READ_BIT ); // адрес ведомого + бит записи
messageBuf[1] = 0x12; // данные
TWI_Start_Transceiver_With_Data( messageBuf, 2 );
_delay_us(100);
messageBuf[0] = ( 0x27 << TWI_ADR_BITS ) | ( FALSE << TWI_READ_BIT ); // адрес ведомого + бит записи
messageBuf[1] = 0x30; // данные
TWI_Start_Transceiver_With_Data( messageBuf, 2 );
Вижу, все хорошо!
Вложение:
2.jpg [102.96 KiB]
Скачиваний: 8


Пробую через 10мкрС...
Код:
 messageBuf[0] = ( 0x27 << TWI_ADR_BITS ) | ( FALSE << TWI_READ_BIT ); // адрес ведомого + бит записи
messageBuf[1] = 0x12; // данные
TWI_Start_Transceiver_With_Data( messageBuf, 2 );
_delay_us(10);
messageBuf[0] = ( 0x27 << TWI_ADR_BITS ) | ( FALSE << TWI_READ_BIT ); // адрес ведомого + бит записи
messageBuf[1] = 0x30; // данные
TWI_Start_Transceiver_With_Data( messageBuf, 2 );
Отправилось только второя часть и завис на СТАРТЕ, линии SDA и SCL в низком уровне.
Вложение:
2_2.jpg [94.48 KiB]
Скачиваний: 7

А в библиотеке дисплея такие задержки есть
Код:
void lq_writeDevicePulse(LiquidCrystalDevice_t* device, uint8_t value)
{
lq_transmitI2C(device, value | LCD_ENABLE_BIT);
_delay_us(2);

lq_transmitI2C(device, value & ~LCD_ENABLE_BIT);
_delay_us(50);
};
только в этой функции, далее не нашел менее 150мкрС. Почему так тупит при малых задержках между отправками? Например в библиотеке INA226 при другой рабочей библиотеке TWI там между отправкой адреса с битом записи и отправкой данных - 10мкрС интервал.

Добавлено after 57 seconds:
Уважаемые форумчане, нужна ваша помощь)))


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 3 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 31


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y