Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F100 USART1 виснет в прерывании. Что делаю не так?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
NeoMage
STM32F100 UART1 когда уходит на прерывание - зависает. Точку останова на прерывании не
ставиться (IAR 6.21).
Если обработчик прерывания оставляю пустым (оставляю только сброс прерывания)- тоже
виснет.
Причем программа работает, а как только от компьютера отправляю байт контроллеру - он
виснет, даже если функция по приему прерывания пустая.
Может неправильно биты прерывания сбрасываю и он в цикл уходит?
Полная программа во вложении. Помогите пожалуйста.
.... инициализация ....
.....
USART1->CR1 |= USART_CR1_TE;
USART1->CR1 |= USART_CR1_RE;
USART1->CR1 |= USART_CR1_RXNEIE;
.....
Обработчик прерывания (отправляет/принемает в буфер)
....
void USART1_IRQHandler(void)
{
if((USART1->SR & USART_SR_RXNE)) //Если прием
{
USART1->SR &= ~USART_SR_RXNE; //сброс флага
rx1_buffer[rx1w] = USART1->DR ; // сохраняем байт в буфер
if(rx1w >= (RX1_BUFFER_SIZE - 1)) //
{
rx1w = 0; //
} else {
rx1w++; //
};
};
if((USART1->SR & USART_SR_TXE)) //по опустошению
{
USART1->SR &= ~USART_SR_TXE; //сброс флага
USART1->DR = tx1_buffer[tx1r];
if(tx1r >= (TX1_BUFFER_SIZE - 1)) //
{
tx1r = 0; //
} else {
tx1r++; //
};
tx1_count++;
if(tx1_count == TX1_BUFFER_SIZE) USART1->CR1 &= ~USART_CR1_TXEIE; //Если все отправили -
выключаем прерывание на отправку
}
}
toweroff
Не скажу точно по этому контроллеру, но, как правило, регистра состояния прерывания в самом начале читается в отдельную переменную
В конце прерывания нужно еще делать

VICVectAddr = 0; /* Acknowledge Interrupt */

но это для ARM7 NXP

ну или в любом случае сбрасывать флаг прерывания. Как он сбрасывается - чтением регистра состояния или обнулять нужно конкретные биты - лезем в даташит в VIC
NeoMage
Написано, что флаг сбрасывается при чтении регистра. Но я его еще на всякий случай сбрасываю:
USART1->SR &= ~USART_SR_RXNE; //сброс флага
_Артём_
Цитата(NeoMage @ Jun 11 2012, 22:46) *
Но я его еще на всякий случай сбрасываю:
USART1->SR &= ~USART_SR_RXNE; //сброс флага

Интересно на какой случай?

Цитата(NeoMage @ Jun 11 2012, 22:46) *
Написано, что флаг сбрасывается при чтении регистра.

Так же написано такое:
Цитата
This clearing sequence is recommended only for multibuffer
communication.


P.S. Интересно что такое "multibuffer communication"?
kan35
У вас как мне кажется USART1_IRQHandler - получился не обработчик, а просто функция.
Для того, чтобы она стала обработчиком нужно включить в проект стандартный *.s файл с векторами прерываний, в котором и будет прописано имя USART1_IRQHandler на определенном месте.Он и точку останова не ставит у вас только потому, что компилятор оптимизирует эту процедуру, так как она не вызывается ниоткуда и ни к чему не привязана.
toweroff
Цитата(kan35 @ Jun 12 2012, 23:14) *
У вас как мне кажется USART1_IRQHandler - получился не обработчик, а просто функция.
Для того, чтобы она стала обработчиком нужно включить в проект стандартный *.s файл с векторами прерываний, в котором и будет прописано имя USART1_IRQHandler на определенном месте.Он и точку останова не ставит у вас только потому, что компилятор оптимизирует эту процедуру, так как она не вызывается ниоткуда и ни к чему не привязана.

прочь, мухи, прочь! даешь котлеты!
ierofant
QUOTE
STM32F100 UART1 когда уходит на прерывание - зависает.


Как зависает? Вываливается в Hard Fault или зацикливается в обработчике?

Попробуйте считывать статус-регистр в буффер, потом уже с буфера проверять, установлены ли флаги. Вот работающий пример, проверьте, может где-то ошиблись:

CODE
void init_uart()
{
RCC->APB2ENR|= RCC_APB2ENR_AFIOEN; // Тактирование альтернативных функций GPIO.
RCC->APB2ENR|= RCC_APB2ENR_USART1EN; // Включение тактирования USART1.
GPIOA->CRH |= GPIO_CRH_MODE9; // Вывод TX PA.9 - на выход.
GPIOA->CRH &=~GPIO_CRH_CNF9; GPIOA->CRH |=GPIO_CRH_CNF9_1; // Альтернативный выход.
USART1->CR1 |=(USART_CR1_RE | USART_CR1_TE); // Разрешить выводы RX, TX.
// Скорость 9.6 kbps. USARTDIV=FSYS/(16*baud) = 24e6/(16*9600)=156.25
USART1->BRR=(156<<4); // Целая часть коэффициента деления USART1.
USART1->BRR|=4; // Дробная часть*16 = 0,25*16 = 4.
USART1->CR1 |=USART_CR1_UE; // Включение USART1.
USART1->CR1 |=USART_CR1_RXNEIE; // Разрешить прерывания RXNE.
NVIC_EnableIRQ(USART1_IRQn); // Разрешить прерывание USART1_IRQn в NVIC.
NVIC_SetPriority(USART1_IRQn, 3); //Задать приоритет прерыванию
}

void USART1_IRQHandler (void) // Обработчик USART1.
{
uint16_t status = USART1->SR;
if (status & USART_SR_RXNE)// Если прерывание по приёму.
{
....
}
else if (status & USART_SR_TXE) // Если прерывание по осовобождению передатчика.
{
....
}
USART1->SR&=~(USART_SR_TXE|USART_SR_RXNE); //очистка флагов
}

void begin_uart_transm()
{
USART1->CR1 |=USART_CR1_TXEIE;
}
NeoMage
Цитата(kan35 @ Jun 12 2012, 23:14) *
У вас как мне кажется USART1_IRQHandler - получился не обработчик, а просто функция.
Для того, чтобы она стала обработчиком нужно включить в проект стандартный *.s файл с векторами прерываний, в котором и будет прописано имя USART1_IRQHandler на определенном месте.Он и точку останова не ставит у вас только потому, что компилятор оптимизирует эту процедуру, так как она не вызывается ниоткуда и ни к чему не привязана.

kan35, Именно так. Спасибо. Как только добавил startup_stm32f10x_ld_vl.s в проект все заработало.
toweroff
Цитата(NeoMage @ Jun 13 2012, 18:54) *
kan35, Именно так. Спасибо. Как только добавил startup_stm32f10x_ld_vl.s в проект все заработало.

тогда мне непонятно. Зачем подключать s-файл с объявленными именами обработчиков прерывания? разве недостаточно описать функцию с __irq и прописать ее в VIC?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.