zoukankan      html  css  js  c++  java
  • 【转】发送串口中断

    我将其改为真正的中断发送。
    步骤一:初始化GPIO
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;         //LED1-PC10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
     
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;          //USART1 TX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);          //A端口
     
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;             //USART1 RX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //复用开漏输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);               //A端口
    12345678910111213
    步骤二:开时钟
    /* Enable USART1, GPIOA, GPIOD and AFIO clocks */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC
                             | RCC_APB2Periph_AFIO, ENABLE);
    123
    在此说明,不用设置RCC_APB2Periph_AFIO也是可以的,也就是在此没有使用复用功能。这两个步骤与查询方式是一样的。
    步骤三:初始化USART1
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_2;
    USART_InitStructure.USART_Parity = USART_Parity_No;      //设置奇校验时,通信出现错误
    USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
     /* Configure the USART1 */
    USART_Init(USART1, &USART_InitStructure);
     /* Enable the USART Transmoit interrupt: this interrupt is generated when the
    USART1 transmit data register is empty */
    USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
     /* Enable the USART Receive interrupt: this interrupt is generated when the
      USART1 receive data register is not empty */
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
     /* Enable USART1 */
    USART_Cmd(USART1, ENABLE);
    12345678910111213141516
    在这里要使能USART1的外设中断,如USART_ITConfig(USART1, USART_IT_TXE, ENABLE);这就是使能发送中断,但发送寄存器空时能产生中断。
    步骤四:编写中断函数
    #define TxBufferSize1   (countof(TxBuffer1) - 1)
    #define RxBufferSize1   (countof(TxBuffer1) - 1)
    #define countof(a)   (sizeof(a) / sizeof(*(a)))      //表示数组a中元素的个数
     
    uint8_t TxBuffer1[] = "USART Interrupt Example: This is USART1 DEMO";
    uint8_t RxBuffer1[RxBufferSize1],rec_f;
    __IO uint8_t TxCounter1 = 0x00;
    __IO uint8_t RxCounter1 = 0x00;
    uint8_t NbrOfDataToTransfer1 = TxBufferSize1;
    uint8_t NbrOfDataToRead1 = RxBufferSize1;
     
     
    /*串口中断服务程序*/
    void USART1_IRQHandler(void)
    {
      unsigned int i;
      /*接收中断*/
      if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
      {  
        /* Read one byte from the receive data register */
        RxBuffer1[RxCounter1++] = USART_ReceiveData(USART1);
        if(RxCounter1 == NbrOfDataToRead1)  //接收数据达到需要长度,则将数据复制到发送数组中,并置标志
        {                    
          /* Disable the USART1 Receive interrupt */
          //USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
            for(i=0; i< RxCounter1; i++) TxBuffer1[i]  = RxBuffer1[i];
            rec_f=1;
            RxCounter1=0;
            TxCounter1=0;
            USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  //打开发送中断,这句是关键
        }
      }
      /*发送中断*/
      if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
      { 
     
        USART_SendData(USART1, TxBuffer1[TxCounter1++]);
     
        if(TxCounter1 == NbrOfDataToTransfer1)//发送数据完成
        {  
          USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //关闭发送中断
        }  
      }  
    }
    1234567891011121314151617181920212223242526272829303132333435363738394041424344
    至此程序就结束了。
    我们就会有个疑问,main()只包括前三个步骤的初始化和一个死循环,那么中断又是如何触发的呢,main()的结构如下:
    int main(void)
    {
     /* System Clocks Configuration */
     RCC_Configuration();
     /* NVIC configuration */
     NVIC_Configuration();
     /* Configure the GPIO ports */
     GPIO_Configuration();
     USART_Configuration();
     
     while (1)
     {
     }
    }
    1234567891011121314
    原来是这样的:状态寄存器USART_SR的复位值为0x00C0H, 也就是第七位TXE和第六位TC复位值为1,而TXE=1,表明发送数据寄存器为空, TC=1表明发送已完成。而在USART的设置中有
     USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    12
    这两句使能中断,也就是说当TXE=1就会进入中断,所以程序初始化后就能进入中断,执行
    if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
     { 
        /* Write one byte to the transmit data register */
          USART_SendData(USART1, TxBuffer[TxCounter++]);
        if(TxCounter == NbrOfDataToTransfer)
        {
          /* Disable the USART1 Transmit interrupt */
          USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
        }
     }
    12345678910
    因此建议的是在初始化时不好启用TXE中断,只在要发送数据(尤其是字符串、数组这样的系列数据)时才启用TXE。在发送完成后立即将其关闭,以免引起不必要的麻烦。
    对于发送,需要注意TXE和TC的差别——这里简单描述一下,假设串口数据寄存器是DR、串口移位寄存器是SR以及TXD引脚TXDpin,其关系是DR->SR->TXDpin。当DR中的数据转移到SR中时TXE置1,如果有数据写入DR时就能将TXE置0;如果SR中的数据全部通过TXDpin移出并且没有数据进入DR,则TC置1。并且需要注意TXE只能通过写DR来置0,不能直接将其清零,而TC可以直接将其写1清零。
    对于发送单个字符可以考虑不用中断,直接以查询方式完成。
    对于发送字符串/数组类的数据,唯一要考虑的是只在最后一个字符发送后关闭发送中断,这里可以分为两种情况:对于发送可显示的字符串,其用0x00作为结尾的,因此在ISR中就用0x00作为关闭发送中断(TXE或者TC)的条件;第二种情况就是发送二进制数据,那就是0x00~0xFF中间的任意数据,就不能用0x00来判断结束了,这时必须知道数据的具体长度。
    来自 http://huangchuanlong.blog.163.com/blog/static/14709020201281921233833/
    ---------------------
    作者:刘Zzr
    来源:CSDN
    原文:https://blog.csdn.net/weixin_43202477/article/details/84848295
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    POJ 1426 Find The Multiple(数论——中国同余定理)
    POJ 2253 Frogger(Dijkstra变形——最短路径最大权值)
    POJ 3790 最短路径问题(Dijkstra变形——最短路径双重最小权值)
    POJ 3278 Catch That Cow(模板——BFS)
    HDU 1071 The area
    HDU 1213 How Many Tables(模板——并查集)
    POJ 1611 The Suspects
    light oj 1214 Large Division
    POJ 1258 Agri-Net(Prim算法求解MST)
    POJ 2387 Til the Cows Come Home(模板——Dijkstra算法)
  • 原文地址:https://www.cnblogs.com/zhangbing12304/p/10881858.html
Copyright © 2011-2022 走看看