Здравствуйте.
Использую контроллер STM32F030F4P6. К нему по I2C подключен 1-Wire Master DS2482-100, а к нему, в свою очередь, по 1-Wire подключен термометр DS1820.
В Keil 5 написан следующий код.
Инициализация I2C:
CODE
void i2c1_init(void)
{
GPIO_InitTypeDef PORT;
I2C_InitTypeDef I2C_INIT;
I2C_StructInit(&I2C_INIT);
I2C_INIT.I2C_Ack = I2C_Ack_Disable;
I2C_INIT.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_INIT.I2C_Mode = I2C_Mode_I2C;
I2C_INIT.I2C_OwnAddress1 = 0xAA;
I2C_INIT.I2C_AnalogFilter = I2C_AnalogFilter_Disable;
I2C_INIT.I2C_DigitalFilter = 0;
I2C_INIT.I2C_Timing = 0x20000A0D; // Расчитано в Excel-таблице I2C_Timing_Configuration_V1.0.1.xls от ST
I2C_DeInit(I2C1);
PORT.GPIO_Mode = GPIO_Mode_AF;
PORT.GPIO_OType = GPIO_OType_OD;
PORT.GPIO_PuPd = GPIO_PuPd_NOPULL;
PORT.GPIO_Speed = GPIO_Speed_2MHz;
PORT.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_Init(GPIOA, &PORT);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_4);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_4);
I2C_Init(I2C1, &I2C_INIT);
I2C_Cmd(I2C1, ENABLE);
}
Работа с DS2482-100:
CODE
t1 = 0;
t2 = 0;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET);
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET);
I2C_SendData(I2C1, 0xF0);
while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET);
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET);
I2C_SendData(I2C1, 0xB4);
while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET);
do
{
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
} while (I2C_ReceiveData(I2C1) & 0x01);
I2C_TransferHandling(I2C1, DS2482A_Addr, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET); // Зависает здесь
I2C_SendData(I2C1, 0xA5);
I2C_SendData(I2C1, 0xCC);
while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET);
do
{
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
} while (I2C_ReceiveData(I2C1) & 0x01);
/*
I2C_TransferHandling(I2C1, DS2482A_Addr, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET);
I2C_SendData(I2C1, 0xA5);
I2C_SendData(I2C1, 0x44);
while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET);
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
while(I2C_ReceiveData(I2C1) & 0x01) {}
*/
I2C_TransferHandling(I2C1, DS2482A_Addr, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET);
I2C_SendData(I2C1, 0xA5);
I2C_SendData(I2C1, 0xBE);
while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET);
do
{
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
} while (I2C_ReceiveData(I2C1) & 0x01);
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET);
I2C_SendData(I2C1, 0x96);
while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET);
I2C_TransferHandling(I2C1, DS2482A_Addr, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET);
I2C_SendData(I2C1, 0xE1);
I2C_SendData(I2C1, 0xE1);
while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET);
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
t1 = I2C_ReceiveData(I2C1);
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET);
I2C_SendData(I2C1, 0x96);
while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET);
do
{
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
} while (I2C_ReceiveData(I2C1) & 0x01);
I2C_TransferHandling(I2C1, DS2482A_Addr, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET);
I2C_SendData(I2C1, 0xE1);
I2C_SendData(I2C1, 0xE1);
while(I2C_GetFlagStatus(I2C1, I2C_ISR_TC) == RESET);
I2C_TransferHandling(I2C1, DS2482A_Addr, 1, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
t2 = I2C_ReceiveData(I2C1);
while(I2C_GetFlagStatus(I2C1, I2C_ISR_STOPF) == RESET);
I2C_ClearFlag(I2C1, I2C_ICR_STOPCF);
Если данный код вручную прошагать в отладчике, то никаких проблем не проявляется и в переменных t1 и t2 будут 0x05 и 0x50, как и указано в даташите на DS18B20.
Однако при обычном запуске программа зависает на четвертом блоке кода на проверке флага TXIS (отмечено комментарием). Флаг TXIS действительно не установлен, при этом флаг TXE установлен, хотя как я понял из даташита, в данном случае они должны подниматься вместе. Также установлен флаг TC, а NACKF, ARLO и другие сняты.
Если установить Breakpoint на строчку выше (I2C_TransferHandling) и выполнить Step Over, то TXIS будет установлен и работа продолжится.
Перепробовал множество вариантов, итог всегда один - пошагово работает, при обычном запуске виснет на проверке флага. У кого-нибудь было такое поведение I2C периферии STM32F0?
Сообщение отредактировал IgorKossak - Nov 8 2015, 17:52
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!