Jump to content

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


Nicollo
 Share

Recommended Posts

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

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

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 - такая же фигня.

Link to comment
Share on other sites

Реклама: ООО ТД Промэлектроника, ИНН: 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);

 

Edited by Mishany
Link to comment
Share on other sites

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 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);      

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

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

Link to comment
Share on other sites

Как измерить внутреннее сопротивление литиевого аккумулятора. Измеряем правильно

Внутреннее сопротивление – один из наиболее значимых параметров, от которого напрямую зависят другие характеристики литиевого аккумулятора. От этого параметра зависят такие характеристики источника питания, как напряжение на выходе под нагрузкой, максимальный выходной ток и коэффициент полезного действия (КПД). Рассмотрим как измерить действительное значение внутреннего сопротивления АКБ, используя определенные методики. Подробнее>>

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

Только что, 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.

 

Edited by BARS_
Link to comment
Share on other sites

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

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

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

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

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

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

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

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

Edited by dosikus
Link to comment
Share on other sites

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

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

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

Link to comment
Share on other sites

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, ну или также можно вручную сбросить. 

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

Link to comment
Share on other sites

 

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++]);
	}
}



 

Edited by dosikus
Link to comment
Share on other sites

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);
	}
}

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

Link to comment
Share on other sites

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);
	}
}

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

Link to comment
Share on other sites

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

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

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

 

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

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

#define USARTCLK 72000000UL

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

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

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

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

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

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

Edited by dosikus
Link to comment
Share on other sites

8 minutes ago, dosikus said:

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

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

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

Link to comment
Share on other sites

Сперва 

Цитата

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

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

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

Edited by dosikus
Link to comment
Share on other sites

4 minutes ago, dosikus said:

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

Адаптер: FT232RL. PUTTY

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

 

Link to comment
Share on other sites

2 minutes ago, dosikus said:

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

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

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

Link to comment
Share on other sites

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

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

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

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

if(USART1->SR & USART_SR_RXNE)

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

Edited by dosikus
Link to comment
Share on other sites

я думаю, я нашел причину. Я использую 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:

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

Edited by Nicollo
Link to comment
Share on other sites

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

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 );
	}
}

 

Edited by mail_robot

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

Link to comment
Share on other sites

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

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

Edited by dosikus
Link to comment
Share on other sites

Во первых сперва почитай кого ты в говнокодерстве обвиняешь, а во вторых причем здесь бездумнонатыканнаяхрень в калокубе????

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...