串口通信深度剖析(二)

-回复 -浏览
楼主 2018-06-26 13:44:16
举报 只看此人 收藏本贴 楼主

串口通信深度剖析二



串口通信深度剖析一小马哥讲解了串口通信的基础知识、通信协议等,串口通信深度剖析二开始将基于STM32单片机对相关干货实例化,包括单片机端串口通信开发,PC端串口通信开发、Android端、iOS端蓝牙串口通信开发等

其实对于STM32等32位单片机开发初期来说,串口通信更多的是作为一种调试手段,借助于PC端串口上位机可以很方便,直观化对代码进行调试本文将基于此对STM32单片机的USART进行很简单的配置,从而使用printf和scanf进行串口通信交互

对于STM32单片机来说,串口资源是非常丰富的,本文基于STM32F4单片机进行测试,其他系列单片机甚至其他单片机类似;详情可以查看《STM32F4XX中文参考手册》第26单元。

不管是使用库函数方法,亦或寄存器方法配置起来都是非常简单的,这里两者兼提供,首先是库函数模板核心代码:

usart.h头文件

 1#ifndef __USART_H
2#define __USART_H
3
4#include "stm32f4xx.h"
5#include "stdio.h"
6
7void USART1_Init(u32 bound);
8
9#endif
10
11/**
12  * @}
13  */

14
15/**
16  * @}
17  */

18
19/*************** (H) Chen Bing *****END OF FILE****/
20


usart.c源文件

 1/******************************************************************************
2@ File name --> usart.c
3@ Author    --> By@ Bing Chen
4@ E-mail    --> chen2725878184@outlook.com
5@ Version   --> V1.0
6@ Date      --> 6 - 20 - 2018
7@ Brief     --> MCU串口简单配置
8*
9
@ Copyright (C) 20**
10@ All rights reserved
11*******************************************************************************
12  *                                   Update
13  *
14******************************************************************************/
15
16/* Includes ------------------------------------------------------------------*/
17#include "usart.h"
18
19/******************************Code area************************************/
20
21/*******************************************************************************
22@Name     : USART1_Init
23@brief    : USART1初始化配置
24@Input    : bound: 串口波特率
25@Output   : None
26@retval   : None
27*******************************************************************************/
28void USART1_Init(u32 bound)
29{
30    GPIO_InitTypeDef    GPIO_InitStructure;
31    USART_InitTypeDef   USART_InitStructure;
32
33    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);            //使能GPIOA时钟
34    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);           //使能USART1时钟
35
36    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);         //PA9复用为USART1
37    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);        //PA10复用为USART1
38
39    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;                      //复用功能
40    GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;                    //推挽复用输出
41    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9 | GPIO_Pin_10;           //选择USART1对应的管脚:PA9->USART1_TX,PA10->USART1_RX
42    GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;                      //上拉
43    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;                //端口速度100MHz
44    GPIO_Init(GPIOA,&GPIO_InitStructure);                           //GPIO端口初始化
45
46    USART_InitStructure.USART_BaudRate=bound;                                     //串口波特率设置:115200
47    USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //设置有无硬件流控制:无
48    USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;                   //模式设置:接收&发送使能
49    USART_InitStructure.USART_Parity=USART_Parity_No;                             //设置有无奇偶校验:无
50    USART_InitStructure.USART_StopBits=USART_StopBits_1;                          //设置停止位:1位
51    USART_InitStructure.USART_WordLength=USART_WordLength_8b;                     //设置数据位:8位
52    USART_Init(USART1,&USART_InitStructure);                                      //USART1初始化
53
54    USART_Cmd(USART1, ENABLE);      //USART1使能
55}
56
57/*******************************************************************************
58@Name     : fputc
59@brief    : 内部调用函数,注意要勾选OPTIONS中的USE Micro LIB选项
60*             由于printf执行是调用fputc函数,所以相当于重新定义printf函数
61*             ,支持printf()发送数据。
62@Input    : None
63@Output   : None
64@retval   : None
65*******************************************************************************/
66int fputc(int ch,FILE *f)
67{
68    USART_SendData(USART1,(u8)ch);
69    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);       //获取串口状态
70    return ch;
71}
72
73/*******************************************************************************
74@Name     : fgetc
75@brief    : 内部调用函数,注意要勾选OPTIONS中的USE Micro LIB选项
76*             由于scanf执行是调用fgetc函数,所以相当于重新定义scanf函数
77*             ,支持printf()发送数据。
78@Input    : None
79@Output   : None
80@retval   : None
81*******************************************************************************/
82int fgetc(FILE *f)
83{
84  while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == RESET);        //获取串口状态
85  return (USART_ReceiveData(USART1));
86}
87
88/**
89  * @}
90  */
91
92/**
93  * @}
94  */
95
96/************************ (C) Chen Bing *****END OF FILE****/


main.c源文件

 1/******************************************************************************
2@ File name --> main.c
3@ Author    --> By@ Bing Chen
4@ E-mail    --> chen2725878184@outlook.com
5@ Version   --> V1.0
6@ Date      --> 06 - 20 - 2018
7@ Brief     --> STM32串口通信交互简单测试
8*
9
@ Copyright (C) 20**
10@ All rights reserved
11*******************************************************************************
12  *                                   Update
13  *
14******************************************************************************/
15
16/* Includes ------------------------------------------------------------------*/
17#include<stm32f4xx.h>
18#include "delay.h"
19#include "nvic.h"
20#include "usart.h"
21#include "led.h"
22
23int main(void)
24{
25    u8 s[100];
26
27    delay_init();
28    NVIC_Priority_Init();
29    USART1_Init(115200);
30    LED_Init();
31
32  while(1)
33  {
34        printf("请随便给我输入点什么: ");
35        scanf("%s",s);
36        LED1 = !LED1;
37        delay_ms(300);
38        printf("%s\r\n",s);
39  }
40}
41
42/**
43  * @}
44  */
45
46/**
47  * @}
48  */
49
50/************************ (C) Chen Bing *****END OF FILE****/




下载之后效果如下:

以上是库函数配置核心源码,下面是寄存器配置核心源码:

usart.h头文件

 1#ifndef __USART_H
2#define __USART_H
3
4#include "stm32f4xx.h"
5#include "stdio.h"
6
7void USART1_Init(u32 pclk2,u32 bound);
8
9#endif
10
11/**
12  * @}
13  */

14
15/**
16  * @}
17  */

18
19/************************ (H) Chen Bing *****END OF FILE****/


usart.c源文件

  1/******************************************************************************
 2@ File name --> usart.c
 3@ Author    --> By@ Bing Chen
 4@ E-mail    --> chen2725878184@outlook.com
 5@ Version   --> V1.0
 6@ Date      --> 06 - 20 - 2018
 7@ Brief     --> MCU串口简单配置
 8*
 9
@ Copyright (C) 20**
10@ All rights reserved
11*******************************************************************************
12  *                                   Update
13  *
14******************************************************************************/
15
16/* Includes ------------------------------------------------------------------*/
17#include "usart.h"
18
19/******************************Code area************************************/
20
21/*******************************************************************************
22@Name     : USART1_Init
23@brief    : USART1初始化配置
24@Input    : pclk2:PCLK2时钟频率(Mhz)    bound: 串口波特率
25@Output   : None
26@retval   : None
27*******************************************************************************/
28void USART1_Init(u32 pclk2,u32 bound)
29{
30    float temp;
31    u16 mantissa;
32    u16 fraction;      
33    temp = (float)(pclk2 * 1000000) / (bound * 16);     //得到USARTDIV@OVER8=0
34    mantissa = temp;                                                                    //得到整数部分
35    fraction = (temp - mantissa) * 16;                              //得到小数部分@OVER8=0 
36    mantissa <<= 4;
37    mantissa += fraction; 
38
39    RCC->
AHB1ENR |= 1 << 0;   //使能PORTA口时钟  
40    RCC->
APB2ENR |= 1 << 4;     //使能串口1时钟 
41
42    /********************************************************************/
43    //PA9->
USART_TX端口初始化配置
44    GPIOA->MODER &= ~(3 << (9 * 2));    //先清除原来的设置
45    GPIOA->
MODER |=  (2 << (9 * 2));    //设置新的模式:复用功能模式
46
47    GPIOA->
OTYPER &= ~(1 << 9) ;        //清除原来的设置
48    GPIOA->
OTYPER |=    (0 << 9);       //设置新的输出模式:输出推挽模式
49
50    GPIOA->
OSPEEDR &= ~(3 << (9 * 2));  //清除原来的设置
51    GPIOA->
OSPEEDR |=  (3 << (9 * 2));  //设置新的速度值:100MHz
52
53    GPIOA->
PUPDR &= ~(3 << (9 * 2));    //先清除原来的设置
54    GPIOA->
PUPDR |=  (1 << (9 * 2));    //设置新的上下拉:上拉模式
55
56    GPIOA->
AFR[1] |= 0x00000070;        //复用为AF7->USART1_TX
57
58    //PA10->USART_RX端口初始化配置
59    GPIOA->MODER &= ~(3 << (10 * 2));   //先清除原来的设置
60    GPIOA->
MODER |=  (2 << (10 * 2));   //设置新的模式:复用功能模式
61
62    GPIOA->
OTYPER &= ~(1 << 10) ;       //清除原来的设置
63    GPIOA->
OTYPER |=    (0 << 10);      //设置新的输出模式:输出推挽模式
64
65    GPIOA->
OSPEEDR &= ~(3 << (10 * 2)); //清除原来的设置
66    GPIOA->
OSPEEDR |=  (3 << (10 * 2)); //设置新的速度值:100MHz
67
68    GPIOA->
PUPDR &= ~(3 << (10 * 2));   //先清除原来的设置
69    GPIOA->
PUPDR |=  (1 << (10 * 2));   //设置新的上下拉:上拉模式
70
71    GPIOA->
AFR[1] |= 0x00000700;        //复用为AF7->USART1_RX
72    /********************************************************************/
73
74    /********************************************************************/
75    //USART1初始化配置
76    USART1->BRR = mantissa;     //波特率设置
77
78    USART1->CR1 &= ~(1 << 15);  //设置OVER8=0
79
80    USART1->
CR1 |= 1 << 3;      //串口发送使能
81
82    USART1->
CR1 |= 1 << 2;      //串口接收使能    
83
84    USART1->
CR1 |= 1 << 13;     //串口使能
85    /********************************************************************/
86}
87
88/*******************************************************************************
89* @Name     : fputc
90* @brief    : 内部调用函数,注意要勾选OPTIONS中的USE Micro LIB选项
91*             由于printf执行是调用fputc函数,所以相当于重新定义printf函数
92*             ,支持printf()发送数据。
93* @Input    : None
94* @Output   : None
95* @retval   : None
96*******************************************************************************/
97int fputc(int ch,FILE *f)
98{
99    while((USART1->
SR & 0X40) == 0);
100    USART1->DR = (u8)ch;
101
102    return ch;
103}
104
105/*******************************************************************************
106@Name     : fgetc
107@brief    : 内部调用函数,注意要勾选OPTIONS中的USE Micro LIB选项
108*             由于scanf执行是调用fgetc函数,所以相当于重新定义scanf函数
109*              ,支持printf()发送数据。
110@Input    : None
111@Output   : None
112@retval   : None
113*******************************************************************************/
114int fgetc(FILE *f)
115{
116    while((USART1->SR & 0x20) == 0);  
117    return ((int)(USART1->DR & 0X1FF)); 
118}
119
120/**
121  * @}
122  */
123
124/**
125  * @}
126  */
127
128/************************ (C) Chen Bing *****END OF FILE****/
129


main.c源文件

 1/******************************************************************************
2@ File name --> main.c
3@ Author    --> By@ Bing Chen
4@ E-mail    --> chen2725878184@outlook.com
5@ Version   --> V1.0
6@ Date      --> 06 - 20 - 2018
7@ Brief     --> STM32串口通信交互简单测试
8*
9
@ Copyright (C) 20**
10@ All rights reserved
11*******************************************************************************
12  *                                   Update
13  *
14******************************************************************************/
15
16/* Includes ------------------------------------------------------------------*/
17#include<stm32f4xx.h>
18#include "delay.h"
19#include "nvic.h"
20#include "sys.h"
21#include "usart.h"
22#include "led.h"
23
24int main(void)
25{
26    u8 s[100];
27
28    delay_init();       //初始化延时函数
29    NVIC_Priority_Init();
30    USART1_Init(84,115200);
31    LED_Init();
32
33  while(1)
34  {
35        printf("请随便给我输入点什么: ");
36        scanf("%s",s);
37        LED1 = !LED1;
38        delay_ms(300);
39        printf("%s\r\n",s);
40  }
41}
42
43/**
44  * @}
45  */
46
47/**
48  * @}
49  */
50
51/************************ (C) Chen Bing *****END OF FILE****/
52



寄存器版本下载之后的效果和库函数是一样的


本文相关手册源码工程会打包到串口通信深度剖析三




以上资料仅供学习使用,更多信息请关注微信公众号:

热爱科技       享受生活

作者:若者

长按二维码关注


往期文章推荐:


硬件设计 | 小马哥DragonFly四轴硬件视频01讲

硬件设计|小马哥DragonFly四轴硬件视频02讲上

硬件设计|小马哥DragonFly四轴硬件视频02讲下

硬件设计|小马哥DragonFly四轴硬件视频03讲上

硬件设计|小马哥DragonFly四轴硬件视频03讲下

硬件设计|小马哥DragonFly四轴硬件视频04讲上

硬件设计|小马哥DragonFly四轴硬件视频04讲下

硬件设计|小马哥DragonFly四轴硬件视频05讲

串口通信深度剖析一(和小马哥聊天记录)

STM32学习教程分享

有奖征稿(初版方案)

关于小芯





合作伙伴同步更新公号内容,欢迎关注:

公号名

步步惊芯

微信号

bubujxin

联系人

小芯


如需帮助,请在下方留言或微信公众号内回复消息





我要推荐
转发到