Форум РадиоКот https://radiokot.ru/forum/ |
|
Stm32F103 +I2C (не выставляет адрес) https://radiokot.ru/forum/viewtopic.php?f=59&t=130323 |
Страница 1 из 1 |
Автор: | pokk [ Ср апр 20, 2016 03:18:01 ] |
Заголовок сообщения: | Stm32F103 +I2C (не выставляет адрес) |
Добрый день, встречалось у кого нибудь такая проблема, что после загрузки адреса slave функцией I2C_Send7bitAddress(I2C2, I2C_ADDR_LCD_KEY_LED, I2C_Direction_Transmitter); он ПЕРИОДИЧЕСКИ не выставляется и соответственно дальше идет зависание на ожидании флага ADDR. Причем это "периодически" примерно зависит от периода запуска функции Send_data_tread Код: while(1){ Send_data_tread(...) delay(); } при delay=0 функцию работает при увеличении delay она виснит на какой-то магической цифре, а при дальнейшем увеличении опять работает. Т.е в рабочей программе это выглядит как 10-700 раз сработала, а потом зависла. Переписывание функции с работой напрямую с регистрами нечего не дает, результат такой же. Код: PT_THREAD(Send_data_tread(struct pt *pt,unsigned char data1,unsigned char data2,unsigned char id)){
static struct pt Init_i2c1; static unsigned char data[2]; static unsigned char i; //---------- PT_BEGIN(pt); PT_INIT(&Init_i2c1); PT_WAIT_THREAD(pt,I2C_Setup_fsm(&Init_i2c1)); while(1){ Start: data[0]=data1; data[1]=data2; /* initiate start sequence */ I2C_GenerateSTART(I2C2, ENABLE); /* check start bit flag */ UB_Led_ON(LED_DEBUG_I2C); while(!I2C_GetFlagStatus(I2C2, I2C_FLAG_SB)){PT_YIELD(pt);}; /*send write command to chip*/ I2C_Send7bitAddress(I2C2, I2C_ADDR_LCD_KEY_LED, I2C_Direction_Transmitter); i=0; do{ if(i>30){ //Если адрес всё ещё не отправился то отправляем повторно(через стоп иначе тоже не отправляется). //Этот костыль спасает, но программа почти регулярно работает через него. i=0; UB_Led_OFF(LED_DEBUG_I2C); goto Start; } i++; PT_YIELD(pt); } //Зависает на этом условии на проверки бита ADDR while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /*check master is now in Tx mode*/ //---------- /*mode register address*/ I2C_SendData(I2C2, data[0]); //---------- /*wait for byte send to complete*/ while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){PT_YIELD(pt);}; //3600 Speed=100Khz /*clear bits*/ I2C_SendData(I2C2, data[1]); //---------- /*wait for byte send to complete*/ while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){PT_YIELD(pt);}; //---------- /*generate stop*/ I2C_GenerateSTOP(I2C2, ENABLE); PT_END_YIELD(pt); } PT_END(pt); //error } |
Автор: | Alexey_N [ Ср июн 15, 2016 13:49:52 ] |
Заголовок сообщения: | Re: Stm32F103 +I2C (не выставляет адрес) |
Все там должно работать, не знаю как на си, но у меня работает вот так (осторожно, asm): СпойлерКод: ;************************************************ ;* desc: Посылает команду старт для I2C для * ;* передачи/приема * ;* in: r2 - режим: 0 - передача * ;* 1 - прием * ;* r3 - адрес устройства * ;* out: Z = 0 - успешно * ;* Z = 1 - таймаут события EV5 или EV6 * ;* used: r0 - r3 * ;* mod: - * ;************************************************ if used _i2c_start align 4 _i2c_start: push {r0-r3, lr} ; Ждем готовности шины I2C ldr r1, [_i2c_base] virtual at r1 .i2c I2C_RegMap end virtual movs r0, 20 bl _wait_minit @@: ldr r0, [.i2c.SR2] tst r0, I2C_SR2_BUSY beq @f bl _wait_check bne @r eors r0, r0 pop {r0-r3, pc} @@: bl _wait_stop ; Посылаем команду START ldr r0, [.i2c.CR1] orrs r0, I2C_CR1_START str r0, [.i2c.CR1] ; Ждем EV5 - бит SB в SR1 @@: ldr r0, [.i2c.SR1] tst r0, I2C_SR1_SB beq @r ldr r0, [.i2c.SR1] ; Сброс SB чтением SR1 ; Посылаем адрес ведомого ands r2, 1 lsls r3, 1 orrs r3, r2 strb r3, [.i2c.DRb] ; Ждем EV6 - бит ADDR в SR1 movs r0, 20 bl _wait_minit @@: ldr r0, [.i2c.SR1] tst r0, I2C_SR1_ADDR bne @f bl _wait_check bne @r eors r0, r0 ; Z = 1 pop {r0-r3, pc} @@: bl _wait_stop ldr r0, [.i2c.SR1] ; Сброс ADDR чтением ldr r0, [.i2c.SR2] ; регистров SR1 и SR2 movs r0, 1 ; Z = 0 pop {r0-r3, pc} end if Когда я разбирался с I2C шиной у меня тоже зависало на этом флаге, ошибка была в неправильном адресе устройства, который выставляется на шину (логическим анализатором обнаружил), он должен быть сдвинут на 1 бит влево (где-то читал, что в сишной функции как раз в этом косяк). На проверку флага лучше повесить таймаут, чтобы не зависать на нем, а обработать как ошибку. |
Автор: | RusikOk [ Вс сен 11, 2016 13:44:04 ] |
Заголовок сообщения: | Re: Stm32F103 +I2C (не выставляет адрес) |
рабочий пример http://cad.life/index/vstraivaemyie-sis ... amyat.html |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |