|
stm32 i2c |
|
|
|
Jul 10 2013, 12:22
|
Группа: Новичок
Сообщений: 4
Регистрация: 9-07-13
Из: СПб
Пользователь №: 77 447

|
Тээк.. Если прерывание разрешено в таймере (бит Update interrupt flag), плюс не запрещены прерывания в целом (PRIMASK = 0), следовательно дело может быть в запрете в NVIC? Или я еще что-то упускаю?
|
|
|
|
|
Jul 10 2013, 12:45
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(drcepera @ Jul 10 2013, 15:22)  Если прерывание разрешено в таймере (бит Update interrupt flag), плюс не запрещены прерывания в целом (PRIMASK = 0), следовательно дело может быть в запрете в NVIC? Нужно вызвать функцию разрешения прерывания в NVIC: NVIC_EnableIRQ(Номер прерывания таймера); Цитата(drcepera @ Jul 10 2013, 15:22)  Или я еще что-то упускаю? Тактирование таймера включено? Нужные флаги в статусе устанавливаются?
|
|
|
|
|
Jul 10 2013, 13:08
|
Группа: Новичок
Сообщений: 4
Регистрация: 9-07-13
Из: СПб
Пользователь №: 77 447

|
Цитата(_Артём_ @ Jul 10 2013, 16:45)  Нужно вызвать функцию разрешения прерывания в NVIC:
NVIC_EnableIRQ(Номер прерывания таймера);
Тактирование таймера включено? Нужные флаги в статусе устанавливаются? Товарищи, таймер-то включен и NVIC именно так и проинициализирован, и прерывания происходят. КРОМЕ случая зависания в указанном месте CPAL. Более того, если при этом я разорву линию I2C - программа выйдет из этого цикла, т.к. __CPAL_I2C_HAL_GET_BUSY(pDevInitStruct->CPAL_Dev) возвращает 0 - и дальше программа будет продолжать работать хорошо, в смысле, прерывания таймеров возобновятся. Цитата Так определите, кто (где, почему) запретил прерывание, если оно не вызывается. Вот я и спрашиваю, если в регистрах таймера все в порядке и не запрещены прерывания - то дело может быть в запрете прерывания в NVIC, либо же еще в чем-нибудь?
|
|
|
|
|
Jul 10 2013, 16:38
|
Местный
  
Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866

|
Цитата(drcepera @ Jul 10 2013, 17:08)  то дело может быть в запрете прерывания в NVIC, либо же еще в чем-нибудь? Чудес не бывает. Когда снова "зависните" - проанализируйте отладчиком регистры, NVIC в том числе. Может, например, Вы в обработчике прерывания забываете сбрасывать pending бит события таймера или что-то в этом роде.
--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
|
|
|
|
|
Jul 10 2013, 19:23
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(KnightIgor @ Jul 11 2012, 12:32)  Мастер определяет, сколько читать/писать. Если у ведомого запросить больше, чем он может дать, он выставит NACK. Я извиняюсь за некропостинг, но это не так. Если у ведомого запросить больше, он может вообще ничего не делать - посылает подтверждения (или неподтверждения) приёмник, т.е. мастер. В этом случае мы получим много-много FF-ов, если слейв-передатчик отпустит шину вообще. Его дело - правильно подтвердить посылку с собственным адресом, и всё.
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Jul 19 2013, 09:38
|
Группа: Новичок
Сообщений: 4
Регистрация: 9-07-13
Из: СПб
Пользователь №: 77 447

|
OMG.. Извиняюсь, товарищи. Нашел таки косяк ) Датчик читался по таймеру А, а таймауты отслеживались по таймеру В. Хоть приоритет у В был и выше, чем А, они были в одной группе. Установил NVIC_PriorityGroup_2 - все, кажется, Ок. Не учел, что прерывания из одной группы не обрывают друг друга.
Спасибо всем за ответы! )
|
|
|
|
|
Feb 25 2014, 11:16
|
Частый гость
 
Группа: Участник
Сообщений: 92
Регистрация: 27-12-12
Из: Томск
Пользователь №: 74 999

|
Хочу поднять эту тему. Пытаюсь завести I2C через CPAL вместе с freeRTOSом. Подскажите как в cpal_conf.h замутить таймер через vApplicationTickHook(), который у меня отсчитывает миллисекунды. Я так полагаю это делается В от здесь. Но как правильно это дело задефайнить не догоняю. Код /* -- Section 4 : **** Configure Timeout method, TimeoutCallback ****
Description: This section allows you to implement your own Timeout Procedure. By default Timeout procedure is implemented with Systick timer and CPAL_I2C_TIMEOUT_Manager is defined as SysTick_Handler. */
#define _CPAL_TIMEOUT_INIT() SysTick_Config((SystemCoreClock / 1000));\ NVIC_SetPriority (SysTick_IRQn, 0) /*<! Configure and enable the systick timer to generate an interrupt when counter value reaches 0. In the Systick interrupt handler the Timeout Error function is called. Time base is 1 ms */
#define _CPAL_TIMEOUT_DEINIT() SysTick->CTRL = 0 /*<! Disable the systick timer */
#define CPAL_I2C_TIMEOUT_Manager SysTick_Handler /*<! This callback is used to handle Timeout error. When a timeout occurs CPAL_TIMEOUT_UserCallback is called to handle this error */ #ifndef CPAL_I2C_TIMEOUT_Manager void CPAL_I2C_TIMEOUT_Manager(void); #else void SysTick_Handler(void); #endif /* CPAL_I2C_TIMEOUT_Manager */
/*#define CPAL_TIMEOUT_UserCallback (void)*/ /*<! Comment this line and implement the callback body in your application in order to use the Timeout Callback. It is strongly advised to implement this callback, since it is the only way to manage timeout errors. */ В общем основной вопрос как прикрутить к CPAL свой собственный таймер.
|
|
|
|
|
Feb 26 2014, 16:57
|
Знающий
   
Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594

|
Я убрал всю инициализацию таймеров в CPAL (закомментив тело вами показанных макросов) Код #define _CPAL_TIMEOUT_INIT() /*SysTick_Config((SystemCoreClock / 1000));\ NVIC_SetPriority (SysTick_IRQn, 0) */ /*<! Configure and enable the systick timer to generate an interrupt when counter value reaches 0. In the Systick interrupt handler the Timeout Error function is called. Time base is 1 ms */
#define _CPAL_TIMEOUT_DEINIT() /*SysTick->CTRL = 0*/ /*<! Disable the systick timer */
/*#define CPAL_I2C_TIMEOUT_Manager SysTick_Handler*/ /*<! This callback is used to handle Timeout error. When a timeout occurs CPAL_TIMEOUT_UserCallback is called to handle this error */
/*#define CPAL_TIMEOUT_UserCallback (void) */ /*<! Comment this line and implement the callback body in your application in order to use the Timeout Callback. It is strongly advised to implement this callback, since it is the only way to manage timeout errors. */ и сделал так: Код void SysTick_Handler(void) { xPortSysTickHandler(); CPAL_I2C_TIMEOUT_Manager(); }
|
|
|
|
|
Feb 27 2014, 10:16
|
Частый гость
 
Группа: Участник
Сообщений: 92
Регистрация: 27-12-12
Из: Томск
Пользователь №: 74 999

|
А ещё такой вопрос, не касающийся CPAL: может ли быть такое что используя стандартную библиотеку STM в режиме Мастер не отпускает линию что бы принять ACK от слэйва после отправки адреса устройства? Просто некоторое время slave нормально отвечал, затем я немного решил порефакторить код и всё сломалось. Вернул на место, всё равно ничего не работает. Смотрю по осцилограмме - слэйв не отправляет ACK. Хотя в его работе вообще ничего меняться не должно было. Выкладываю код: Инициализация: CODE //Инициализация GPIO RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // SCL пин GPIO_InitStruct.GPIO_Pin = I2C1_SCL_PIN; GPIO_Init(I2C1_SCL_PORT, &GPIO_InitStruct); GPIO_PinAFConfig(I2C1_SCL_PORT, I2C1_SCL_PIN_SOURCE, GPIO_AF_I2C1); // SDA пин GPIO_InitStruct.GPIO_Pin = I2C1_SDA_PIN; GPIO_Init(I2C1_SDA_PORT, &GPIO_InitStruct); GPIO_PinAFConfig(I2C1_SDA_PORT, I2C1_SDA_PIN_SOURCE, GPIO_AF_I2C1); // Конфигурация I2C RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); I2C_Cmd(I2C1, DISABLE); I2C_DeInit(I2C1); I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStruct.I2C_OwnAddress1 = I2C1_OWN_ADDRESS; I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStruct.I2C_ClockSpeed = I2C_SPEED; I2C_Init(I2C1, &I2C_InitStruct); // Включение интерфейса I2C_Cmd(I2C1, ENABLE); чтение регистра CODE // Проверка готовности линии while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); // Генерация первого старта I2C_GenerateSTART(I2Cx, ENABLE); // Проверка что линия свободна while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // Отправка адреса подчинённого устройства (запись) I2C_Send7bitAddress(I2Cx, slaveAddress, I2C_Direction_Transmitter); // Проверка ACK от подчинённого устройства (есть ли такой адрес на шине) while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // Отправка адреса регистра чтения I2C_SendData(I2Cx, regAddress); // Проверка ACK от подчинённого устройства while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // Генерация повторного старта I2C_GenerateSTART(I2Cx, ENABLE); // Проверка что линия свободна while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // Отправка адреса подчинённого устройства (чтение) I2C_Send7bitAddress(I2Cx, slaveAddress, I2C_Direction_Receiver); // Проверка ACK от подчинённого устройства while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); // Завершаем приём I2C_AcknowledgeConfig(I2Cx, DISABLE); // Проверка что байт принят (данные загружены в регистр DR) while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); // Генерируем стоп I2C_GenerateSTOP(I2C1, ENABLE); return I2C_ReceiveData(I2Cx); И после первой отправки адреса устройства ACK я так и не дожидаюсь. Устройство STA381BWS. Добавил к коду сдвиг адреса Slave'а на один бит влево. Ничего не изменилось.
Сообщение отредактировал Ruslan-maniak - Feb 28 2014, 07:43
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|