首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在运行主程序的同时在STM32f103xx上正确实现UART1中断?

如何在运行主程序的同时在STM32f103xx上正确实现UART1中断?
EN

Stack Overflow用户
提问于 2020-12-07 16:50:11
回答 1查看 77关注 0票数 0

我正在尝试对我的bluePill进行编程,使其在PB11引脚上闪烁发光二极管,同时响应通过串行端口UART1发送的内容。

据我所知,中断允许我们运行我们想要的程序,在运行它的时候,如果任何标志触发了中断信号,程序的控制将被转移到运行中断服务例程,而原始程序正在运行,我说的对吗?

因此,我正在尝试保持绿色LED闪烁,当我在串行端口上输入任何内容时,红色LED闪烁,而绿色闪烁,除非正在发送数据,否则蓝色led必须始终亮起。

问题1:绿色的led从不闪烁!

问题2:每当通过Arduino串行监视器发送字母或数字时,收到的回声总是整个发送字母中的2个字母,而且回声总是在同一行上,我的意思是不是在换行符上,所以键入Hello并按enter键将生成He,而当键入hi there并按enter键时,它只添加前两个字母,如so Hehi,为什么?

我的代码是

代码语言:javascript
复制
/* ********************** Project Description ***********************
    STM32f103xx BluePill Board
    PB10 = Green LED
    PB11 = Blue LED (To be toggled)
    PB0 = Red LED (PWM OUTPUT Controlling the Brightness)
    PB9 = Push Button for toggling the state of the blue LED
    PA0 = Potentiomater Pin (Analog Input)
    USART1 Activated and Sends the Voltage of PA0 to the user1



*/


#include "stm32f1xx.h"  // Include the MCU header
#include <stdbool.h>    // Boolean Library header
#include <stdint.h>


// Prototypes:
void UART1_Init(void);              //Enable UART1 on PA9(Tx) & PA10(Rx).
void portsEnable(void);             //Enable Clock for desired MCU Ports.
void delay(uint32_t delay);         //Intuduce Delays.
void pinsConfig(void);              //Configure the used pins.


// Defines and Macros



int main(void)
{
  // Inintialization:
  portsEnable();
  pinsConfig();
  UART1_Init(); // Enable USART1 & interrupts @ 8Mhz clock Speed only @ 9600Bps

  while(1)
  {
    // ********  Blink The green LED ***********************
    GPIOB->BSRR = GPIO_BSRR_BS11;
    delay(100000);
    GPIOB->BSRR = GPIO_BSRR_BR11;
    delay(100000);

  } // End of while loop
} // End main() loop

// ************** Function Implimentation *****************************
void UART1_Init(void)                         // Initiallize USART1
{
  // Reset Setting (8bit, one stop bit, no parity)
  // Enable clock for UART1 First after already enabling the PortA clock
  RCC->APB2ENR |= RCC_APB2ENR_USART1EN;       // Enable Clock to the USART1 Module

  // Pin Configuration for the USART1 Peripheral where Tx(PA9) = AF Push-Pull and Rx = Input Floating
  
  // Setting Tx (PA9) Pin
  GPIOA->CRH |= ((1<<4) | (1<<5));      // Set PA9 to Output 50Mhz Mode
  GPIOA->CRH &= ~(1<<6);                // Configure it to be an AF push-pull
  GPIOA->CRH |= (1<<7);                 // Same as above^
  
  // Setting Rx (PA10) pin
  // Nothing to be set as the reset value makes it an input pin with floating configuration
  
  // Set the Baud-Rate
  USART1->BRR = 0x341;    //@ 8Mhz, USARTDIV = 8Mhz/(16*9600) = 52.083 -> 52=0x34 and 0.083 * 16 = 1.328 = 1 which is 0x1  

  // Enable Interrupts for the USART1 Module:
  // A peripheral can generates a flag at a certain event, this flag can trigger an interrupt signal but first the certain event interrupt must be enabled and the peripheral interrupt as well and the global interrupts.
  USART1->CR1 |= USART_CR1_TXEIE | USART_CR1_RXNEIE;    // Enable the Transmit Data Register Empty Interrupt register and data received interrupt

  // Enable the Tx, Rx, USART1 as a whole block
  USART1->CR1 |= (USART_CR1_RE | USART_CR1_TE | USART_CR1_UE);

  // Enable the USART1 Global interrupt on NVIC "Nested Vectored Interrupt controller" side. The NVIC is the interrupt processing unit in the MCU.
  NVIC_EnableIRQ(USART1_IRQn);  // This function's name can't be changed!
}
// This is a global interrupt service routine, any flag from the USART1 will lead to the same ISR, to distinguesh which is which we check the the flags and if one is set then this what caused the interrupt
void USART1_IRQHandler(void)                  // This function's name must be the same as it's defined in the main libraries
{
    // Check if we are here because we Received Data or simply the "RXNE flag is set".
    if(USART1->SR & USART_SR_RXNE)  // If Rx is Not Empty, or if we received Data, The USART1->SR register is going to change as it is controlled by the hardwart and we compare it to the value of the register USART_SR_RXNE which indicates a 1 at bit5
    {
      char temp = USART1->DR;  // Read the 8bit data received fron the data register into a char called temp
      USART1->DR = temp;       // Put the same data in the data register to be resent again, here the data registers are clled shadow registers they are not the same registers from the hardware prospective but from programming prospective we use the same registers
      
      while(!(USART1->SR & USART_SR_TC))
      {
        // Wait while the transmission completes and indicate the waiting process by flashing the RED led indicating data being sent.
        GPIOB->BSRR = GPIO_BSRR_BR10;      // When not ready to accept more data (e.g. while transmitting data process) turn of the Blue LED
        GPIOB->BSRR = GPIO_BSRR_BS1;
        delay(10000);
        GPIOB->BSRR = GPIO_BSRR_BR1;
      }

    } 

      // Check if we are here because the TXEIE is set "OR the Transmit complete" meaning we are ready to accept more data to transmit
      if(USART1->SR & USART_SR_TXE)
      {
        // Handle transmit complete here: (Blink an LED)
        GPIOB->BSRR = GPIO_BSRR_BS10;       // When Ready to accept more data
      }
      else
      {
        GPIOB->BSRR = GPIO_BSRR_BR10;      // When not ready to accept more data (e.g. while transmitting data process) 
      }
      
    
}

void portsEnable(void)                        /* Enable PortA and PortB */
{
  // Enable clock for Ports (A & B) on "APB2" Bus.
  RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;       // Enable PortA Clock
  RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;       // Enable PortB Clock
}

void pinsConfig(void)                         //Configure the used pins.
{  
  //Set pin "PB1" as output push-pull (Red LED)
  GPIOB->CRL |= ((1<<4) | (1<<5));          //Set Pin to Output 50Mhz max speed
  GPIOB->CRL &= ~((1<<6) | (1<<7));         //Configure Pin as Push-Pull


  //Set Pin "PB9" as Input Pulled-Up (Push Button Pin)
  GPIOB->CRH &= ~(1<<6);                   //Set PB9 to input "pullup|pulldown"
  GPIOB->CRH |= (1<<7);
  GPIOB->ODR |= (1<<9);                    //Set PB9 input pin as Pull-up pin.


  //Set pin "PB10" as output push-pull (Blue LED)
  GPIOB->CRH |= ((1<<9) | (1<<8));          //Set Pin to Output 50Mhz max speed
  GPIOB->CRH &= ~((1<<11) | (1<<10));       //Configure Pin as Push-Pull

  //Set pin "PB11" as output push-pull (Green LED)
  GPIOB->CRH |= ((1<<12) | (1<<13));        //Set Pin to Output 50Mhz max speed
  GPIOB->CRH &= ~((1<<14) | (1<<15));       //Configure Pin as Push-Pull


  //Set pin PA0 as Analog input
  GPIOA->CRL &= ~((1<<0) | (1<<1));          // Make sure the Mode registers are 00 for input
  GPIOA->CRL &= ~((1<<2) | (1<<3));          // Set the CNF registers to 00 for input analog
  
} // End PinsConfig()

void delay(uint32_t delay)                    /* Psudo-delay in Milliseconds */
{
    for(uint32_t i = 0; i <= delay; i++)
    {
      // Looping to delay!
    }
}
EN

回答 1

Stack Overflow用户

发布于 2021-01-01 22:53:49

也许下面的链接对你有帮助:stm32 dead lock

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65178548

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档