Перейти к содержанию

stm32f103c8t6 прерывание по приему USART1


Nicollo

Рекомендуемые сообщения

Добрый вечер.

Решил недавно поиграться с микроконтроллерами, ибо были в загашнике такие платы: 

Ayx1N.png

Ппробовал погонять данные по USART. В обычном режиме - все работает нормально, но вот с прерываниями - немного не получается. 

Я взял пример из стандартной библиотеки, скомпилил, залил и прерывание не срабатывает.

#include <stm32f10x.h>
#include <misc.h>

volatile char received_string[MAX_STRLEN+1];

void Delay(__IO uint32_t nCount) {
  while(nCount--) {
  }
}

void init_USART1(uint32_t baudrate){

   GPIO_InitTypeDef GPIO_InitStruct;
   USART_InitTypeDef USART_InitStruct;
   NVIC_InitTypeDef NVIC_InitStructure;

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);


   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOA, &GPIO_InitStruct);

   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
   GPIO_Init(GPIOA, &GPIO_InitStruct);

   USART_InitStruct.USART_BaudRate = baudrate;
   USART_InitStruct.USART_WordLength = USART_WordLength_8b;
   USART_InitStruct.USART_StopBits = USART_StopBits_1;
   USART_InitStruct.USART_Parity = USART_Parity_No;
   USART_InitStruct.USART_HardwareFlowControl =    USART_HardwareFlowControl_None;
   USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
   USART_Init(USART1, &USART_InitStruct);

   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);


   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
   NVIC_Init(&NVIC_InitStructure);      

   USART_Cmd(USART1, ENABLE);
}

void USART_puts(USART_TypeDef* USARTx, volatile char *s){

   while(*s){
      while( !(USARTx->SR & 0x00000040) );
      USART_SendData(USARTx, *s);
      *s++;
   }
}

int main(void) {

  init_USART1(9600); // initialize USART1 @ 9600 baud

  USART_puts(USART1, "Init complete! Hello World!\r\n"); // just send a message to indicate that it works

   while (1){
     /*
      * You can do whatever you want in here
      */
   }
}

void USART1_IRQHandler(void){

    // check if the USART1 receive interrupt flag was set
    if( USART_GetITStatus(USART1, USART_IT_RXNE) ){

        static uint8_t cnt = 0; // this counter is used to determine the string length
        char t = USART1->DR; // the character from the USART1 data register is saved in t

        // check if the received character is not the LF character (used to determine end of string)
        // or the if the maximum string length has been been reached
        if( (t != '\n') && (cnt < MAX_STRLEN) ){
            received_string[cnt] = t;
            cnt++;
        }
         else{ // otherwise reset the character counter and print the received string
           cnt = 0;
           USART_puts(USART1, received_string);
        }
    }
}

Решил упростить задачу и поморгать светодиодом:
 

void USART2_IRQHandler(void){
	USART_ClearITPendingBit(USART2, USART_IT_TC);
	USART_ClearITPendingBit(USART2, USART_IT_RXNE);
	static uint8_t isSet = SET;
	GPIO_WriteBit(GPIOC , GPIO_Pin_13 , isSet);
	isSet = !isSet;
}

Оно в обработчик вообще не попадает. 

Подскажите, может что не так делаю?
Отладчика пока нету, заказал - жду.

Есть FTD USB-UART преобразователи, через них прошиваю и проверяю. 

А еще я в основной цикл добавил постоянную отправку строки, и оно таки прерывается, когда я шлю байт с компа, но в обработчик оно, походу, не попадает. Пробовал на USART2 - такая же фигня.

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

помимо чтения USART1->DR

еще надо и

USART1->SR

в конце не хватает очистки флага прерывания

//очистка флага прерывания
USART_ClearITPendingBit(USART1, USART_IT_RXNE);

как то так стоит попробовать:

void  USART1_IRQHandler(void)
{
	if(USART_GetFlagStatus(USART1, USART_IT_RXNE) == SET)
	{
		if ((USART1->SR & (USART_FLAG_NE|USART_FLAG_ORE)) == 0)
		{
			recive_UART1 = USART1->DR;
		}
		//очистка флага прерывания
    	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

 

если не заработает смотреть инициализацию

слепой или нету))

  USART_Init(USART1, &USART_InitStructure); 
  USART_ClearFlag(USART1,USART_FLAG_TC);
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
  USART_Cmd(USART1, ENABLE);

 

Изменено пользователем Mishany
Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

7 minutes ago, dosikus said:

Зачем? Объяснить можем?

Я читал где-то что неявная очистка статус регистра немного хромает, и для подстаховки рекомендуют сбрасывать бит флага прерывания вручную.
 

2Mishany: я так делал, не помогло

Инициализация у меня есть вот такая: 

	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
   	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
   	NVIC_Init(&NVIC_InitStructure);      

Т.е. я хочу чтоб прерывание сработало ТОЛЬКО на приеме.

И мне кажется что прерывание происходит, но в обработчик оно почему-то не попадает

Ссылка на комментарий
Поделиться на другие сайты

Только что, dosikus сказал:

Зачем?

Открываем умный документ и смотрим. Там на чисто англицком сказано, что бит прерывания USART не сбрасывается аппаратно и его требуется сбросить программно (это, кстати, ко многим прерываниям STM относится). В противном случае при попадании в прерывание программа никогда из него не выйдет.

Цитата

This bit is set by hardware when the content of the RDR shift register has been transferred to
the USART_DR register. An interrupt is generated if RXNEIE=1 in the USART_CR1 register.
It is cleared by a read to the USART_DR register. The RXNE flag can also be cleared by
writing a zero to it.

 

Изменено пользователем BARS_
Ссылка на комментарий
Поделиться на другие сайты

6 минут назад, Nicollo сказал:

Я читал где-то что неявная очистка статус регистра немного хромает, и для подстаховки рекомендуют сбрасывать бит флага прерывания вручную.

Где что вы читали ? Кто вообще эту хрень выдвинул?

Читайте RM , а не кухаркины статьи 

RXNE сбрасывается чтением SR с последующим чтением DR .

Причем чтение SR происходит при проверке флага.

И не надо лепить горбатого - все проверенно и работает

BARS_, ту да же - читать RM .

Изменено пользователем dosikus
Ссылка на комментарий
Поделиться на другие сайты

Только что, dosikus сказал:

RXNE сбрасывается чтением SR с последующим чтением DR .

Тогда читайте даташит ВНИМАТЕЛЬНО. Выше я привел абзац, где черным по белому написано, что RXNE очищается записью нуля в него.

Ссылка на комментарий
Поделиться на другие сайты

1 minute ago, BARS_ said:

Тогда читайте даташит ВНИМАТЕЛЬНО. Выше я привел абзац, где черным по белому написано, что RXNE очищается записью нуля в него.

Тут и вы и он равы 

Quote

It is cleared by a read to the USART_DR register. The RXNE flag can also be cleared by
writing a zero to it.

Он сам должен сбрасываться, после прочтения USART_DR, ну или также можно вручную сбросить. 

В любом случае, мою проблему это не решает.

Ссылка на комментарий
Поделиться на другие сайты

 

BARS_,

Читаем внимательно - то что нужно выделил 

Цитата

Bit 5 RXNE: Read data register not empty
This bit is set by hardware when the content of the RDR shift register has been transferred to
the USART_DR register. An interrupt is generated if RXNEIE=1 in the USART_CR1 register.
It is cleared by a read to the USART_DR register. The RXNE flag can also be cleared by
writing a zero to it.
This clearing sequence is recommended only for multibuffer
communication.

Да для сброса RXNE не надо читать SR , но сбрасывается он чтением DR  а также может быть сброшен записью 0 .
BARS_, я удивлен тобой , разве можно читать документацию частями????

Nicollo,  ваша проблема решается элементарно - выкашивается на SPL и все прекрасно работает.

 

#define USARTCLK 72000000UL

#define BAUDRATE 115200UL


void USART1_IRQHandler (void)
 {
 
   if(USART1->SR & USART_SR_RXNE)
   {
     UsartBuf =USART1->DR;
    
   }
   
 }



 void UsartInit(void)
 {
   RCC->APB2ENR |=RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN;
    
    GPIOA->CRH &=~ (GPIO_CRH_CNF10 |GPIO_CRH_CNF9|GPIO_CRH_MODE10);
    GPIOA->CRH |= GPIO_CRH_CNF10_0 |GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9;
    
    USART1->CR1 |= USART_CR1_TE |USART_CR1_RE |USART_CR1_RXNEIE;
    USART1->BRR =(USARTCLK+BAUDRATE/2)/BAUDRATE;
    USART1->CR1 |=USART_CR1_UE;
    
    NVIC_SetPriority(USART1_IRQn,15);
    NVIC_EnableIRQ(USART1_IRQn);
   
   
 }

void USART_write (char data)
  {
    while(!(USART1->SR & USART_SR_TXE));
    USART1->DR=data;
  }
	
void  USART_WR_String(const char *s)
{	int i = 0;
	while (s [i] != 0) {

	USART_write (s[i++]);
	}
}



 

Изменено пользователем dosikus
Ссылка на комментарий
Поделиться на другие сайты

23 minutes ago, dosikus said:

Nicollo,  ваша проблема решается элементарно - выкашивается на SPL и все прекрасно работает.

void init_USART1(uint32_t baudrate){

	RCC_ClocksTypeDef RCC_ClocksStatus;
	RCC_GetClocksFreq(&RCC_ClocksStatus);

	RCC->APB2ENR |=RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN;

	GPIOA->CRH &=~ (GPIO_CRH_CNF10 |GPIO_CRH_CNF9|GPIO_CRH_MODE10);
	GPIOA->CRH |= GPIO_CRH_CNF10_0 |GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9;

	USART1->CR1 |= USART_CR1_TE |USART_CR1_RE |USART_CR1_RXNEIE;
	USART1->BRR =(RCC_ClocksStatus.PCLK2_Frequency+baudrate/2)/baudrate;
	USART1->CR1 |=USART_CR1_UE;


	NVIC_SetPriority(USART1_IRQn,15);
	NVIC_EnableIRQ(USART1_IRQn);
}

void USART_write (char data)
{
	while(!(USART1->SR & USART_SR_TXE));
	USART1->DR=data;
}

void  USART_WR_String(const char *s)
{	int i = 0;
	while (s [i] != 0) {
		USART_write (s[i++]);
	}
}

int main(void) {

  init_USART1(9600); // initialize USART1 @ 9600 baud

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOC , &GPIO_InitStructure);
  GPIO_WriteBit(GPIOC , GPIO_Pin_13 , RESET);

  USART_WR_String("Init complete! Hello World!\r\n"); // just send a message to indicate that it works

  while (1){
    /*
     * You can do whatever you want in here
     */
  }
}

// this is the interrupt request handler (IRQ) for ALL USART1 interrupts
void USART1_IRQHandler(void)
{
	if(USART1->SR & USART_SR_RXNE)
	{
		char recive_UART1 = USART1->DR;
		USART_write(recive_UART1);
	}
}

Не интераптит

Ссылка на комментарий
Поделиться на другие сайты

void USART1_IRQHandler(void)
{
	static uint8_t isSet = SET;
	GPIO_WriteBit(GPIOC , GPIO_Pin_13 , isSet);
	isSet = !isSet;

	if(USART1->SR & USART_SR_RXNE)
	{
		char recive_UART1 = USART1->DR;
		USART_write(recive_UART1);
	}
}

Сделал даже так, помограть диодом - оно в обработчик даже не заходит

Ссылка на комментарий
Поделиться на другие сайты

14 минуты назад, Nicollo сказал:

Не интераптит

А к чему ваши правки ? 

 

Подсказываю метод проверки :

Создаем проект с моим и неправленным кодом , тактовая чипа должна быть 72МГц  если тактовая иная правим здесь 

#define USARTCLK 72000000UL

Подсоединяем через адаптер UART -USB к ББ   и добиваемся устойчивого приема на стороне ББ отправляемых нами строк .

И только потом пробуем отправить с ББ и брякнуться в прерывании.

Да, сперва проверяем адаптер UART -USB замкнув RX и TX адаптера( без подсоединения отлаживаемой платы) и проверяя эхо в терминальной программе.

14 минуты назад, Mishany сказал:

у меня и без выкашивания SPL все прекрасно работает

А у нас в квартире газ...

Изменено пользователем dosikus
Ссылка на комментарий
Поделиться на другие сайты

8 minutes ago, dosikus said:

Подсоединяем через адаптер UART -USB к ББ   и добиваемся устойчивого приема на стороне ББ отправляемых нами строк .

И только потом пробуем отправить с ББ и брякнуться в прерывании...

Подсоединил, сделал как вы написали, на компе строку получил. прерывание не сработало

Ссылка на комментарий
Поделиться на другие сайты

Сперва 

Цитата

Да, сперва проверяем адаптер UART -USB замкнув RX и TX адаптера( без подсоединения отлаживаемой платы) и проверяя эхо в терминальной программе.

Кстати какой адаптер и какая терминальная программа?

И здесь крайне желательно наличие лог. анализатора - сокращает подобные танцы с бубном до минимума...

Изменено пользователем dosikus
Ссылка на комментарий
Поделиться на другие сайты

4 minutes ago, dosikus said:

Кстати какой адаптер и какая терминальная программа?

Адаптер: FT232RL. PUTTY

RX и TX работают. Прием-передачу делал без прерываний в основном цикле - работало без проблем. 

 

Ссылка на комментарий
Поделиться на другие сайты

2 minutes ago, dosikus said:

Вы проверили эхо?

У меня так же все работает и с прерываниями и с DMA , так что ваша реплика -ниАчем ...

Работает эхо, и адаптеры я менял. Оно просто не входит в обработчик, прерывание случается.

Ссылка на комментарий
Поделиться на другие сайты

4 минуты назад, Nicollo сказал:

Оно просто не входит в обработчик, прерывание случается.

Что сие означает? Как вы это проверяете? Что за IDE?

Например Keil - запускаете дебаг , ставите бряк на строку 

if(USART1->SR & USART_SR_RXNE)

Запускаете процесс, жмете кнопку на клаве когда окно putty в фокусе - должно сработать прерывание.

Изменено пользователем dosikus
Ссылка на комментарий
Поделиться на другие сайты

я думаю, я нашел причину. Я использую OpenSTM32 IDE

Оно, при создании проекта, само подгружает SPL так вот, там есть файлик: sturtup_stm32.s

насколько я понял в нем мапятся прерывания с обработчиками, и он не проинициализирован до конца

g_pfnVectors:
	.word	_estack
	.word	Reset_Handler
	.word	NMI_Handler
	.word	HardFault_Handler
	.word	MemManage_Handler
	.word	BusFault_Handler
	.word	UsageFault_Handler
	.word	SVC_Handler
	.word	DebugMon_Handler
	.word	PendSV_Handler
	.word	SysTick_Handler

Я скачал библиотеку с сайта и посмотрел в этот файлик, и он немного отличается. Сейчас попытаюсь запустить проект с новой либой.

Added:

Да, все верно, подменил файл, все заработало. Спасибо всем.

Изменено пользователем Nicollo
Ссылка на комментарий
Поделиться на другие сайты

я обычно предпочитаю в обработчик писать только это

void USART1_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart1);
}

а остальное уже делать в колбэке. Хотя по сути это одно и то же, но зато вероятность ошибиться меньше. Потому как HAL_UART_IRQHandler все флаги сам позсбрасывает там где надо и вызовет нужный колбэк

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if (huart->Instance == USART1)
	{		
		xQueueSendToBackFromISR( displayQueueHandle, &UART1_rxBuffer, 0 );
	}
}

 

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

Здесь не хватало скорости в прерывание из-за SPL http://www.microchip.su/showpost.php?p=231953&postcount=162

Ну а тем кто пользует калокуб можно только посочувствовать , эта гадость из любого чипа сделает тормоз...

Изменено пользователем dosikus
Ссылка на комментарий
Поделиться на другие сайты

Если у вас руки из жопы кодят, то куб то тут при чем?

STM1_WIFI_TEST.ZIP

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...