找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7134|回复: 5
收起左侧

STM32串口通信配置(USART1+USART2+USART3+UART4)

[复制链接]
ID:346927 发表于 2019-5-28 10:50 | 显示全部楼层 |阅读模式
一、串口一的配置(初始化+中断配置+中断接收函数)
  1.   1 /*===============================================================================
  2.   2 Copyright:
  3.   3 Version:
  4.   4 Author:   
  5.   5 Date: 2017/11/3
  6.   6 Description:
  7.   7     配置独立看门狗初始化函数,在主函数中运行IWDG_ReloadCounter进行喂狗主函数必须在4s内进行一次喂狗不然系统会复位;
  8.   8     函数功能是将接收固定长度的字符串,并将接收后的字符串通过串口发送出去
  9.   9 revise Description:
  10. 10 ===============================================================================*/
  11. 11 #include "stm32f10x_usart.h"
  12. 12 #include "stm32f10x.h"
  13. 13 #include "stm32f10x_iwdg.h"
  14. 14
  15. 15 u8 USART1_RX_BUF[21];
  16. 16 u8 USART1_RX_CNT=0;
  17. 17
  18. 18 void IWDG_Configuration(void);
  19. 19
  20. 20 void Usart1_Init(u32 bound)
  21. 21 {
  22. 22     //GPIO端口设置
  23. 23     GPIO_InitTypeDef GPIO_InitStructure;
  24. 24     USART_InitTypeDef USART_InitStructure;
  25. 25     NVIC_InitTypeDef NVIC_InitStructure;
  26. 26      
  27. 27     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE);//使能USART1,GPIOA,C时钟
  28. 28      
  29. 29     //USART1_TX   GPIOA.9
  30. 30     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  31. 31     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  32. 32     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
  33. 33     GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
  34. 34
  35. 35     //USART1_RX      GPIOA.10初始化
  36. 36     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  37. 37     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  38. 38     GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
  39. 39
  40. 40     //Usart1 NVIC 配置
  41. 41     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);    //设置NVIC中断分组2:2位抢占优先级,2位响应优先级   0-3;
  42. 42     
  43. 43     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  44. 44     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
  45. 45     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
  46. 46     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
  47. 47     NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器
  48. 48   
  49. 49    //USART 初始化设置
  50. 50
  51. 51     USART_InitStructure.USART_BaudRate = bound;//串口波特率
  52. 52     USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  53. 53     USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  54. 54     USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  55. 55     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  56. 56     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;    //收发模式
  57. 57
  58. 58     USART_Init(USART1, &USART_InitStructure); //初始化串口1
  59. 59     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  60. 60     USART_Cmd(USART1, ENABLE);                    //使能串口1
  61. 61 }
  62. 62 /**
  63. 63 * USART1发送len个字节.
  64. 64 * buf:发送区首地址
  65. 65 * len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节)
  66. 66 **/
  67. 67 void USART1_Send_Data(u8 *buf,u16 len)
  68. 68 {
  69. 69     u16 t;
  70. 70     GPIO_SetBits(GPIOC,GPIO_Pin_9);
  71. 71 //  RS485_TX_EN=1;            //设置为发送模式
  72. 72     for(t=0;t<len;t++)        //循环发送数据
  73. 73     {           
  74. 74         while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕   
  75. 75         USART_SendData(USART1,buf[t]);
  76. 76     }     
  77. 77     while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);        
  78. 78     GPIO_ResetBits(GPIOC,GPIO_Pin_9);
  79. 79 //    RS485_TX_EN=0;                //设置为接收模式   
  80. 80 }
  81. 81 void main(void)
  82. 82 {
  83. 83     Usart1_Init(9600);//串口1波特率设置为9600
  84. 84     IWDG_Configuration();
  85. 85     while(1)
  86. 86     {
  87. 87         IWDG_ReloadCounter();//4s内必须喂狗不然复位
  88. 88         if(USART1_RX_CNT==21)//数据接收完成
  89. 89         {
  90. 90             USART1_RX_CNT=0;//指针复位
  91. 91             //将接收到的数据发送出去
  92. 92             USART1_Send_Data(USART1_RX_BUF,21);//通过串口1将接收到的固定长度字符发送出去            
  93. 93         }
  94. 94     }
  95. 95     
  96. 96 }
  97. 97 /**
  98. 98 * 接收指定长度的字符串
  99. 99 * 比如接收固定大小为21个字节的字符串
  100. 100 **/
  101. 101 void USART1_IRQHandler(void)                    //串口1中断服务程序
  102. 102 {
  103. 103     u8 Res;
  104. 104     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  105. 105         {
  106. 106             Res =USART_ReceiveData(USART1);    //读取接收到的数据     
  107. 107             if(USART1_RX_CNT<21)//对于接收指定长度的字符串
  108. 108             {
  109. 109                 USART1_RX_BUF[USART1_RX_CNT]=Res;        //记录接收到的值   
  110. 110                 USART1_RX_CNT++;                                        //接收数据增加1
  111. 111             }            
  112. 112      }
  113. 113          //溢出-如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题
  114. 114     if(USART_GetFlagStatus(USART1,USART_FLAG_ORE) == SET)
  115. 115     {
  116. 116         USART_ReceiveData(USART1);
  117. 117         USART_ClearFlag(USART1,USART_FLAG_ORE);
  118. 118     }
  119. 119      USART_ClearFlag(UART1,USART_IT_RXNE); //一定要清除接收中断
  120. 120 }
  121. 121 /*===============================================================================
  122. 122 Copyright:
  123. 123 Version:
  124. 124 Author:   
  125. 125 Date: 2017/11/3
  126. 126 Description:配置独立看门狗初始化函数,在主函数中运行IWDG_ReloadCounter进行喂狗
  127. 127     主函数必须在4s内进行一次喂狗不然系统会复位
  128. 128 revise Description:
  129. 129 ===============================================================================*/
  130. 130 void IWDG_Configuration(void)
  131. 131 {
  132. 132      /* 写入0x5555,用于允许狗狗寄存器写入功能 */
  133. 133     IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
  134. 134      /* 狗狗时钟分频,40K/256=156HZ(6.4ms)*/  
  135. 135     IWDG_SetPrescaler(IWDG_Prescaler_256);    /* 喂狗时间 5s/6.4MS=781 .注意不能大于0xfff*/  
  136. 136     IWDG_SetReload(781);//781(5s时间)
  137. 137     IWDG_SetReload(3125);//781(20s时间)
  138. 138     IWDG_Enable();//启用定时器
  139. 139     IWDG_ReloadCounter();
  140. 140 }
复制代码

二、串口二的配置(初始化+中断配置+中断接收函数)
  1. 1 /*===============================================================================
  2.   2 Copyright:
  3.   3 Version:
  4.   4 Author:   
  5.   5 Date: 2017/11/3
  6.   6 Description:
  7.   7     函数功能是将接收固定长度的字符串,并将接收后的字符串通过串口发送出去
  8.   8 revise Description:
  9.   9 ===============================================================================*/
  10. 10 #include "stm32f10x_usart.h"
  11. 11 #include "stm32f10x.h"
  12. 12 #include "stm32f10x_iwdg.h"
  13. 13
  14. 14
  15. 15 u8 USART2_RX_BUF[250];
  16. 16 u8 USART2_RX_CNT=0;
  17. 17 u16 USART2_RX_STA=0;       //接收状态标记   
  18. 18
  19. 19 void Usart2_Init(u32 bound)
  20. 20 {  
  21. 21     GPIO_InitTypeDef GPIO_InitStructure;
  22. 22     USART_InitTypeDef USART_InitStructure;
  23. 23     NVIC_InitTypeDef NVIC_InitStructure;
  24. 24     //|RCC_APB2Periph_AFIO
  25. 25     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA时钟
  26. 26     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟
  27. 27
  28. 28     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;    //PA2
  29. 29     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽
  30. 30     GPIO_Init(GPIOA, &GPIO_InitStructure);
  31. 31
  32. 32     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
  33. 33     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
  34. 34     GPIO_Init(GPIOA, &GPIO_InitStructure);  
  35. 35
  36. 36     RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);//复位串口2
  37. 37     RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位
  38. 38
  39. 39     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);    //设置NVIC中断分组2:2位抢占优先级,2位响应优先级   0-3;
  40. 40     NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中断
  41. 41     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级2级
  42. 42     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级2级
  43. 43     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
  44. 44     NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
  45. 45
  46. 46     USART_InitStructure.USART_BaudRate = bound;//波特率设置
  47. 47     USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据长度
  48. 48     USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  49. 49     USART_InitStructure.USART_Parity = USART_Parity_No;///奇偶校验位
  50. 50     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  51. 51     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
  52. 52
  53. 53     USART_Init(USART2, &USART_InitStructure); ; //初始化串口
  54. 54     USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断
  55. 55     USART_Cmd(USART2, ENABLE);                    //使能串口
  56. 56
  57. 57 }
  58. 58 /**
  59. 59 * USART2发送len个字节.
  60. 60 * buf:发送区首地址
  61. 61 * len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节)
  62. 62 **/
  63. 63 void USART2_Send_Data(u8 *buf,u16 len)
  64. 64 {
  65. 65     u16 t;
  66. 66       for(t=0;t<len;t++)        //循环发送数据
  67. 67     {           
  68. 68         while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);      
  69. 69         USART_SendData(USART2,buf[t]);
  70. 70     }     
  71. 71     while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);         
  72. 72 }
  73. 73 /**
  74. 74 * 这也是一个接收函数,可以用,也可以用下面main函数的方法调用
  75. 75 * USART2查询接收到的数据
  76. 76 * buf:接收缓存首地址
  77. 77 * len:读到的数据长度
  78. 78 **/
  79. 79 void USART2_Receive_Data(u8 *buf)
  80. 80 {
  81. 81     u8 rxlen=USART2_RX_CNT;
  82. 82     u8 i=0;
  83. 83     delay_ms(10);        //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
  84. 84     while(rxlen!=USART2_RX_CNT)
  85. 85     {
  86. 86         rxlen=USART2_RX_CNT;
  87. 87         delay_ms(10);
  88. 88     }
  89. 89         for(i=0;i<(USART2_RX_CNT);i++)
  90. 90         {
  91. 91             buf[i] = USART2_RX_BUF[i];   
  92. 92             USART2_RX_BUF[i] = 0;
  93. 93         }        
  94. 94         USART2_RX_CNT=0;        //清零
  95. 95     
  96. 96 }
  97. 97
  98. 98 void main(void)
  99. 99 {
  100. 100     Usart2_Init(9600);//串口1波特率设置为9600
  101. 101     while(1)
  102. 102     {
  103. 103         if(USART2_RX_STA)//数据接收完成
  104. 104         {
  105. 105             USART2_RX_STA=0;            
  106. 106             //将接收到的数据发送出去
  107. 107             USART2_Send_Data(USART2_RX_BUF,USART2_RX_CNT);//通过串口1将接收到的固定长度字符发送出去   
  108. 108             USART2_RX_CNT=0;//指针复位
  109. 109         }
  110. 110     }   
  111. 111 }
  112. 112
  113. 113
  114. 114 void USART2_IRQHandler(void)
  115. 115 {
  116. 116     u8 res;        
  117. 117      if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收到数据
  118. 118     {         
  119. 119         res =USART_ReceiveData(USART2);     //读取接收到的数据        
  120. 120         if(USART2_RX_STA==0)
  121. 121         {
  122. 122             USART2_RX_BUF[USART2_RX_CNT] = res;        //记录接收到的值   
  123. 123             //当数据结尾收到0xA0和0xA1代表数据接收完成,是一串完整的数据
  124. 124             if(USART2_RX_BUF[USART2_RX_CNT-1]==0xA0&&USART2_RX_BUF[USART2_RX_CNT]==0xA1)
  125. 125                 USART2_RX_STA=1;//表示接收数据结束
  126. 126             USART2_RX_CNT++;                        //接收数据增加1
  127. 127         }
  128. 128         }
  129. 129     }  
  130. 130     //溢出-如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题
  131. 131     if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) == SET)
  132. 132     {
  133. 133         USART_ReceiveData(USART2);
  134. 134         USART_ClearFlag(USART2,USART_FLAG_ORE);
  135. 135     }
  136. 136      USART_ClearFlag(UART2,USART_IT_RXNE); //一定要清除接收中断   
  137. 137 }
复制代码


三、串口三的配置(初始化+中断配置+中断接收函数)
  1.   1 /*===============================================================================
  2.   2 Copyright:
  3.   3 Version:
  4.   4 Author:   
  5.   5 Date: 2017/11/3
  6.   6 Description:
  7.   7     函数功能是将接收固定长度的字符串,并将接收后的字符串通过串口发送出去
  8.   8     通过滴答定时器方式获取数据
  9.   9 revise Description:
  10. 10 ===============================================================================*/
  11. 11 #include "stm32f10x_usart.h"
  12. 12 #include "stm32f10x.h"
  13. 13
  14. 14 #define USART3_TIMEOUT_Setting 800  //(ms)
  15. 15
  16. 16 u8 USART3_RX_BUF[250];
  17. 17 u16 USART3_RX_CNT=0;
  18. 18 u16 USART3_RX_TIMEOUT=0;       //接收状态标记   
  19. 19
  20. 20 void Timer1CountInitial(void);
  21. 21
  22. 22 void USART3_Init(u32 baud)   
  23. 23 {  
  24. 24     USART_InitTypeDef USART_InitStructure;  
  25. 25     NVIC_InitTypeDef NVIC_InitStructure;   
  26. 26     GPIO_InitTypeDef GPIO_InitStructure;    //声明一个结构体变量,用来初始化GPIO  
  27. 27     //使能串口的RCC时钟  
  28. 28     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); //使能UART3所在GPIOB的时钟  
  29. 29     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);  
  30. 30
  31. 31     //串口使用的GPIO口配置  
  32. 32     // Configure USART3 Rx (PB.11) as input floating   
  33. 33     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  
  34. 34     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
  35. 35     GPIO_Init(GPIOB, &GPIO_InitStructure);  
  36. 36
  37. 37     // Configure USART3 Tx (PB.10) as alternate function push-pull  
  38. 38     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
  39. 39     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  40. 40     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
  41. 41     GPIO_Init(GPIOB, &GPIO_InitStructure);  
  42. 42
  43. 43     //配置串口  
  44. 44     USART_InitStructure.USART_BaudRate = baud;  
  45. 45     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  
  46. 46     USART_InitStructure.USART_StopBits = USART_StopBits_1;  
  47. 47     USART_InitStructure.USART_Parity = USART_Parity_No;  
  48. 48     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  
  49. 49     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  
  50. 50
  51. 51
  52. 52     // Configure USART3   
  53. 53     USART_Init(USART3, &USART_InitStructure);//配置串口3
  54. 54     // Enable USART3 Receive interrupts 使能串口接收中断  
  55. 55     USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);  
  56. 56     // Enable the USART3   
  57. 57     USART_Cmd(USART3, ENABLE);//使能串口3  
  58. 58
  59. 59     //串口中断配置  
  60. 60     //Configure the NVIC Preemption Priority Bits     
  61. 61     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  
  62. 62
  63. 63     // Enable the USART3 Interrupt   
  64. 64     NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;   
  65. 65     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
  66. 66     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;        //子优先级3
  67. 67     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  68. 68     NVIC_Init(&NVIC_InitStructure);      
  69. 69      
  70. 70 }
  71. 71
  72. 72 void USART3_Sned_Char(u8 temp)        
  73. 73 {  
  74. 74     USART_SendData(USART3,(u8)temp);      
  75. 75     while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);  
  76. 76      
  77. 77 }
  78. 78
  79. 79 void USART3_Sned_Char_Buff(u8 buf[],u32 len)  
  80. 80 {  
  81. 81     u32 i;  
  82. 82     for(i=0;i<len;i++)  
  83. 83     USART3_Sned_Char(buf[i]);  
  84. 84           
  85. 85 }
  86. 86
  87. 87 void main(void)
  88. 88 {
  89. 89     Timer1CountInitial();
  90. 90     Usart3_Init(9600);//串口1波特率设置为9600
  91. 91     while(1)
  92. 92     {
  93. 93         if(USART3_RX_TIMEOUT==USART3_TIMEOUT_Setting)
  94. 94         {            
  95. 95             USART3_RX_TIMEOUT=0;
  96. 96             USART3_Sned_Char_Buff(USART3_RX_BUF,USART3_RX_CNT);//将接收到的数据发送出去
  97. 97             USART3_RX_CNT=0;
  98. 98         }
  99. 99         
  100. 100     }   
  101. 101 }
  102. 102 void USART3_IRQHandler(void)                    //串口3中断服务程序
  103. 103 {
  104. 104     u8 Res;
  105. 105     if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  
  106. 106     {   
  107. 107         USART3_RX_TIMEOUT=0;
  108. 108         USART3_RX_BUF[USART3_RX_CNT++] = USART_ReceiveData(USART3);    //读取接收到的数据        
  109. 109     }
  110. 110     //溢出-如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题
  111. 111     if(USART_GetFlagStatus(USART3,USART_FLAG_ORE) == SET)
  112. 112     {
  113. 113         USART_ReceiveData(USART3);
  114. 114         USART_ClearFlag(USART3,USART_FLAG_ORE);
  115. 115     }
  116. 116     USART_ClearITPendingBit(USART3, USART_IT_RXNE);
  117. 117
  118. 118 }
  119. 119
  120. 120 //放到主函数的初始化中初始化
  121. 121 void Timer1CountInitial(void)
  122. 122 {
  123. 123     //定时=36000/72000x2=0.001s=1ms;
  124. 124         TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
  125. 125         ///////////////////////////////////////////////////////////////
  126. 126         RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  127. 127         
  128. 128         TIM_TimeBaseStructure.TIM_Period = 100-1;//自动重装值(此时改为10ms)
  129. 129         TIM_TimeBaseStructure.TIM_Prescaler = 7200-1;//时钟预分频
  130. 130         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
  131. 131         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        //时钟分频1
  132. 132         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;            
  133. 133         TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
  134. 134         
  135. 135         TIM_ClearFlag(TIM1,TIM_FLAG_Update);
  136. 136         TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);  
  137. 137         TIM_Cmd(TIM1, ENABLE);
  138. 138 }
  139. 139 void TIM1_UP_IRQHandler(void)
  140. 140 {        
  141. 141     //TIM_TimeBaseStructure.TIM_Period = 100-1;//自动重装值(此时改为10ms)
  142. 142     if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
  143. 143     {  
  144. 144         if(USART3_RX_TIMEOUT<USART3_TIMEOUT_Setting)
  145. 145                 USART3_RX_TIMEOUT++;        
  146. 146     }
  147. 147     TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
  148. 148 }
复制代码

四、串口四的配置(初始化+中断配置+中断接收函数)

注意串口四的中断优先级没有贴出来,和前面的三个一样的配置,为了不占用过多的篇幅就不贴中断优先级配置了
  1.   1 /*===============================================================================
  2.   2 Copyright:
  3.   3 Version:
  4.   4 Author:   
  5.   5 Date: 2017/11/3
  6.   6 Description:
  7.   7     函数功能是将接收固定长度的字符串,并将接收后的字符串通过串口发送出去
  8.   8     通过滴答定时器方式获取数据
  9.   9 revise Description:
  10. 10 ===============================================================================*/
  11. 11 #include "stm32f10x_usart.h"
  12. 12 #include "stm32f10x.h"
  13. 13
  14. 14 #define USART4_TIMEOUT_Setting 800  //(ms)
  15. 15
  16. 16 u8 USART4_RX_BUF[250];
  17. 17 u16 USART4_RX_CNT=0;
  18. 18 u16 USART2_RX_STA=0;       //接收状态标记
  19. 19
  20. 20 void Systick_delay_init(u8 SYSCLK);
  21. 21 u8 virtual_delay(u32 num,u8 unit);
  22. 22
  23. 23 //通用异步收发器UART4
  24. 24 void UART4_Init(u32 bound)
  25. 25 {
  26. 26     USART_InitTypeDef USART_InitStructure;
  27. 27     GPIO_InitTypeDef GPIO_InitStructure;
  28. 28
  29. 29     //used for USART3 full remap
  30. 30     //GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);
  31. 31     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
  32. 32     RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);//for UART4
  33. 33
  34. 34     //Configure RS485_TX_EN PIN
  35. 35     GPIO_InitStructure.GPIO_Pin = RS485_TX_EN_PIN;                 //PC9端口配置
  36. 36     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //推挽输出
  37. 37     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  38. 38     GPIO_Init(RS485_TX_EN_PORT, &GPIO_InitStructure);
  39. 39
  40. 40     RS485_TX_EN=0;            //设置485默认为接收模式
  41. 41
  42. 42     /* Configure USART Tx as alternate function push-pull */
  43. 43     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  44. 44     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  45. 45     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  46. 46     GPIO_Init(GPIOC, &GPIO_InitStructure);
  47. 47
  48. 48     /* Configure USART Rx as input floating */
  49. 49     GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11;
  50. 50     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  51. 51     GPIO_Init(GPIOC, &GPIO_InitStructure);
  52. 52
  53. 53
  54. 54     USART_InitStructure.USART_BaudRate = bound;
  55. 55     USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  56. 56     USART_InitStructure.USART_StopBits = USART_StopBits_1;
  57. 57     USART_InitStructure.USART_Parity = USART_Parity_No ;
  58. 58     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  59. 59     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  60. 60
  61. 61     USART_Init(UART4, &USART_InitStructure);
  62. 62     //USART_Init(USART3, &USART_InitStructure);
  63. 63     /* Enable the USART */
  64. 64     USART_Cmd(UART4, ENABLE);
  65. 65     USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);//开启串口接受中断
  66. 66     USART_ClearFlag(UART4,USART_FLAG_TC);   
  67. 67 }
  68. 68 //USART1查询接收到的数据
  69. 69 //buf:接收缓存首地址
  70. 70 //len:读到的数据长度
  71. 71 void UART4_Receive_Data(u8 *buf)
  72. 72 {
  73. 73     u8 rxlen=21;
  74. 74     u8 i=0;
  75. 75     delay_ms(10);        //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
  76. 76     
  77. 77     RS485_RX_FLAG = 0;
  78. 78     if((UART4_RX_BUF[0]==0x01)&&(UART4_RX_BUF[1]==0x03))
  79. 79     {
  80. 80         for(i=0;i<rxlen;i++)
  81. 81         {
  82. 82             buf[i]=UART4_RX_BUF[i];   
  83. 83             UART4_RX_BUF[i] = 0;
  84. 84         }   
  85. 85         RS485_RX_FLAG = 1;
  86. 86     }
  87. 87         UART4_RX_CNT=0;        //清零
  88. 88 }
  89. 89
  90. 90
  91. 91 //USART1发送len个字节.
  92. 92 //buf:发送区首地址
  93. 93 //len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节)
  94. 94 void UART4_Send_Data(u8 *buf,u16 len)
  95. 95 {
  96. 96     u16 t;
  97. 97     RS485_TX_EN=1;            //设置为发送模式
  98. 98     for(t=0;t<len;t++)        //循环发送数据
  99. 99     {           
  100. 100         while(USART_GetFlagStatus(UART4,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕   
  101. 101         USART_SendData(UART4,buf[t]);
  102. 102     }     
  103. 103     while(USART_GetFlagStatus(UART4, USART_FLAG_TC) == RESET);        
  104. 104     RS485_TX_EN=0;                //设置为接收模式   
  105. 105 }
  106. 106
  107. 107 void main(void)
  108. 108 {
  109. 109     Systick_delay_init(72);
  110. 110     Usart4_Init(9600);//串口1波特率设置为9600
  111. 111     while(1)
  112. 112     {
  113. 113         if(USART2_RX_STA)
  114. 114         {
  115. 115             if(virtual_delay(USART4_TIMEOUT_Setting,MS))//超过800ms空闲则可以读取数据
  116. 116             {
  117. 117                 UART4_Send_Data(UART4_RX_BUF,UART4_RX_CNT);
  118. 118                 USART2_RX_STA=0;
  119. 119                 UART4_RX_CNT=0;               
  120. 120             }
  121. 121            
  122. 122         }
  123. 123         
  124. 124     }   
  125. 125 }
  126. 126 void UART4_IRQHandler(void)                    //UART4 Receive Interrupt
  127. 127 {
  128. 128     u8 Res;
  129. 129     
  130. 130     if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
  131. 131     {   
  132. 132         Res =USART_ReceiveData(UART4);//(USART1->DR);    //读取接收到的数据   
  133. 133         UART4_RX_BUF[UART4_RX_CNT&0XFF]=Res;        //回传的数据存入数组,0X3F限制为64个数值
  134. 134             UART4_RX_CNT++;
  135. 135         USART2_RX_STA=1;   
  136. 136     }
  137. 137     
  138. 138     if( USART_GetITStatus(UART4, USART_IT_TC) == SET )
  139. 139     {
  140. 140         USART_ClearFlag(UART4, USART_FLAG_TC);
  141. 141     }   
  142. 142     //溢出-如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题
  143. 143     if(USART_GetFlagStatus(UART4,USART_FLAG_ORE) == SET)
  144. 144     {
  145. 145         USART_ReceiveData(UART4);
  146. 146         USART_ClearFlag(UART4,USART_FLAG_ORE);
  147. 147     }
  148. 148 //    USART_ITConfig(UART4, USART_IT_RXNE, DISABLE);//临时关闭接收中断
  149. 149     USART_ClearFlag(UART4,USART_IT_RXNE); //一定要清除接收中断
  150. 150     
  151. 151 }
  152. 152
  153. 153 //初始化延迟函数
  154. 154 //SYSTICK的时钟固定为HCLK时钟的1/8
  155. 155 //SYSCLK:系统时钟
  156. 156 void Systick_delay_init(u8 SYSCLK)
  157. 157 {
  158. 158     SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟  HCLK/8
  159. 159 //    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);    //选择外部时钟  HCLK/8
  160. 160     fac_us=SYSCLK/8;            
  161. 161     fac_ms=(u16)fac_us*1000;
  162. 162 }
  163. 163 /*===============================================================================
  164. 164 Author:peter pan
  165. 165 Date:
  166. 166 Description: 查询式分时或叫做轮询式(近似延时)。本函数是用于执行高效率场合的查询延时,但是一个for or while 循环中只能用一次。
  167. 167 revise Description:  
  168. 168 @ num :    //分时查询的周期计数值   
  169. 169 @ unit :    //分时查询的周期单位
  170. 170     @@ParaValue :
  171. 171         MS    //周期单位为MS毫秒级
  172. 172         US    //周期单位为US微秒级
  173. 173 @ virtual_delay_status :    //静态变量
  174. 174     @@ParaValue :
  175. 175         SET    //SYSTICK正在占用中,请勿用
  176. 176         RESET  //SYSTICK空闲,可以使用
  177. 177 @ReValue :
  178. 178     with zero mean Time non-arrive ,one representative Time arrived ,you can do task;
  179. 179 ##example             if(virtual_delay(1000,MS)) LedFlash();    //1000ms LED闪烁一下
  180. 180 ===============================================================================*/
  181. 181 u8 virtual_delay(u32 num,u8 unit)
  182. 182 {
  183. 183     u32 temp;           
  184. 184     if(virtual_delay_status==RESET)    //  SYSTICK空闲,可以使用
  185. 185       {
  186. 186           if(unit==MS)
  187. 187           {
  188. 188                 SysTick->LOAD=(u32)num*Delay_SYSCLK*125;//时间加载(SysTick->LOAD为24bit)
  189. 189                 SysTick->VAL =0x00;           //清空计数器
  190. 190                 SysTick->CTRL=0x01 ;          //开始倒数  
  191. 191           }else if(unit==US)
  192. 192           {
  193. 193                 SysTick->LOAD=num*Delay_SYSCLK/8; //时间加载               
  194. 194                 SysTick->VAL=0x00;        //清空计数器
  195. 195                 SysTick->CTRL=0x01 ;      //开始倒数     
  196. 196           }
  197. 197           virtual_delay_status=SET;
  198. 198           return 0;
  199. 199         }
  200. 200     else
  201. 201         {        //virtual_delay_status==SET SYSTICK被占用
  202. 202         
  203. 203             temp=SysTick->CTRL;
  204. 204             if(!(temp&0x01&&!(temp&(1<<16))))//等待时间到达   
  205. 205             {
  206. 206                 SysTick->CTRL=0x00;       //关闭计数器
  207. 207                 SysTick->VAL =0X00;       //清空计数器   
  208. 208                 virtual_delay_status=RESET;   
  209. 209                 return 1;
  210. 210             }else return 0;
  211. 211         }
  212. 212 }
复制代码





STM32串口通信配置.pdf

253.31 KB, 下载次数: 80, 下载积分: 黑币 -5

回复

使用道具 举报

ID:142699 发表于 2019-11-4 19:42 | 显示全部楼层
楼主测试过程序么,串口三能发送不能接收数据
回复

使用道具 举报

ID:795735 发表于 2020-7-2 15:20 | 显示全部楼层
串口4不行啊,RS485_TX_EN没有定义
回复

使用道具 举报

ID:795735 发表于 2020-7-2 15:21 | 显示全部楼层
jianfeii 发表于 2019-11-4 19:42
楼主测试过程序么,串口三能发送不能接收数据

串口3我配置通了,
回复

使用道具 举报

ID:797825 发表于 2020-7-5 15:57 | 显示全部楼层
这个串口能否加MODUBUS协议
回复

使用道具 举报

ID:570410 发表于 2020-9-20 23:51 | 显示全部楼层

这几个串口能否加MODUBUS协议,做主站或从站?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表