6、串口通信的基本知识与代码实现

简介: 6、串口通信的基本知识与代码实现

三种不同串口介绍

image.png

串口通信的设置的流程:


  1. 确定主时钟,并进入串口初始化

此时如果选定HSI片内时钟可能会有误差,而HSE的精度可能会好一点

  1. 设置发送数据位数
  2. 设定发送数据校验位及校验方式
  3. 设定发送数据停止位位数
  4. 设定发送数据波特率
  5. 使能发送中断功能

此步也可以直接查询,无需使能中断,有中断就有中断服务函数

  1. 使能发送功能
  2. 发送单字节的数据

可以重定向,重新改写相关的函数就可以了

  1. 等待发送完毕


主要的寄存器:

image.png


  • 帧结构如下图

image.png


  • 如何配置数据位(帧结构的第二个部分)

image.png


  • 如何配置校验位(帧结构的第三个部分)

image.png

校验位与数据帧格式说明

image.png


UART1_CR1 = 0x00;
  //**************************************************
  //展开UART1_CR1赋值二进制数值为:0000 0000 
  //含义:R8=0;    接收数据位不存在第9位
  //      T8=0;    发送数据位不存在第9位
  //      UARTD=0; 使能UART功能
  //      M=0;     一个起始位,8个数据位,n个停止位
  //                n取决于UART1_CR3中的STOP[1:0]位
  //      WAKE=0;   UART被空闲总线唤醒
  //      PCEN=0: (UART模式)奇偶校验控制被禁止
  //      PS=0;    偶校验(校验功能未启用)
  //      PIEN=0;  校验中断被禁止
  //*************************************************


  • 如何设置停止位(帧结构的第三个部分)

image.png

UART1_CR3 = 0x00;
  //**************************************************
  //展开UART1_CR3赋值二进制数值为:0000 0000 
  //含义:保留位=0;必须保持清零
  //      LINEN=0;LIN模式被禁止
  //      STOP=00;配置为“00”,1个停止位
  //      CLKEN、CPOL、CPHA、LBCL这几位在UART3上不存在
  //*************************************************


  • 如何设置波特率

image.png

image.png

注意:BRR1寄存器的两个位不能同时为0,分配值不能小于16(0x000f),否则串口就不能使用,波特率失效

//配置通信波特率参数,此处配置为9600bps(16MHz频率下)
  UART1_BRR2 = 0x03;
  UART1_BRR1 = 0x68;


  • 使能位的设定

image.png

 

//使能发送和接收功能
  UART1_CR2 = 0x0C;
  //**************************************************
  //展开UART1_CR2赋值二进制数值为:0000 1100 
  //含义:TIEN=0;发送中断被禁止
  //     TCIEN=0;发送中断完成被禁止
  //      RIEN=0;接收中断被禁止
  //      ILIEN=0;IDLE中断被禁止
  //      TEN=1;发送功能使能
  //      REN=1;接收功能使能
  //      RWU=0;(UART模式)正常工作模式
  //      SBK=0;未发送断开字符
  //*************************************************
}


  • 状态寄存器(主要用TXE、TC、PE三个位)

image.png

image.png

image.png

image.png

两种发送数据的方式:


  • 第一种:利用指针偏移不断的将字符串输出
/****************************************************************/
//发送单字符函数UART1_SendByte(),有形参data,无返回值
/****************************************************************/
void UART1_SendByte(u8 data)
{
   UART1_SR&=0xBF;//清零发送完成标志位TC
   UART1_DR=data;//发送数据到UART1数据寄存器
   //while (!(UART1_SR & 0x80));//【旧版语句,有瑕疵】等待发送完毕
   //原来的语句是&上了0x80,其实是判断了TXE位,这种方法不严谨,因为
   //发送数据寄存器空不一定说明发送已经完成了,应该判断TC位才正确
   while (!(UART1_SR & 0x40));//【新版语句,推荐】等待发送完毕
   UART1_SR&=0xBF;//清零发送完成标志位TC
}
/****************************************************************/
//发送字符串函数UART1_SendString(),有1个形参Data,无返回值
/****************************************************************/
void UART1_SendString(u8* Data)
{
  while(*Data!='\0')//判断字符串结束标志
  {
    UART1_SendByte(*Data);//把字符串拆分为多个单字节发送动作
    Data++;//指针后移,不断指向新的字符
  }
}
u8 table1[]="************************************************************\r\n";
  UART1_SendString(table1);//发送字符串1
  //UART1_SendByte(0x0D);//回车符号
  //UART1_SendByte(0x0A);//换行符号


  • 第二种:重定义putchar函数,使得可以直接在printf中将数据输出到串口中
/****************************************************************/
//发送单字符函数UART1_SendByte(),有形参data,无返回值
/****************************************************************/
void UART1_SendByte(u8 data)
{
   UART1_SR&=0xBF;//清零发送完成标志位TC
   UART1_DR=data;//发送数据到UART1数据寄存器
   //while (!(UART1_SR & 0x80));//【旧版语句,有瑕疵】等待发送完毕
   //原来的语句是&上了0x80,其实是判断了TXE位,这种方法不严谨,因为
   //发送数据寄存器空不一定说明发送已经完成了,应该判断TC位才正确
   while (!(UART1_SR & 0x40));//【新版语句,推荐】等待发送完毕
   UART1_SR&=0xBF;//清零发送完成标志位TC
}
/****************************************************************/
//发送字符重定向函数putchar(),有形参ch,有返回值
/****************************************************************/
int putchar(int ch) 
{ 
  UART1_SendByte((u8)ch);//将Printf内容发往串口
  return (ch); 
}
  printf("************************************************************\r\n");


可见方法二比较方便,两种方法都可以输出信息。

image.png

  • 接收数据的方式
/****************************************************************/
//接收单字符函数UART1_ReceiveByte(),无形参data,有返回值,返回接收到的数据
//采用查询的方法实现
/****************************************************************/
u8 UART1_ReceiveByte(void)
{
 // printf("进入UART1_ReceiveByte函数...\r\n");
  u8 UART1_RX_BUF;                //定义接收数据暂存变量
  while (!(UART1_SR & 0x20));    //等待接收标志
  UART1_SR&=0xDF;                //清零接收标志位RXNE
  UART1_RX_BUF=UART1_DR;         //取回接收到的数据
 // printf("取回接收到的数据\r\n");
  return  UART1_RX_BUF;         //返回暂存变量中的数据给调用者
}


代码如下:

/****************************************************************/
//初始化函数UART1_Init(),无形参和返回值
/****************************************************************/
void UART1_Init(void)
{
  //1.设定通信数据位数,此处设定为8位数据位,无校验位
  UART1_CR1 = 0x00;
  //**************************************************
  //展开UART1_CR1赋值二进制数值为:0000 0000 
  //含义:R8=0;    接收数据位不存在第9位
  //      T8=0;    发送数据位不存在第9位
  //      UARTD=0; 使能UART功能
  //      M=0;     一个起始位,8个数据位,n个停止位
  //                n取决于UART1_CR3中的STOP[1:0]位
  //      WAKE=0;   UART被空闲总线唤醒
  //      PCEN=0: (UART模式)奇偶校验控制被禁止
  //      PS=0;    偶校验(校验功能未启用)
  //      PIEN=0;  校验中断被禁止
  //*************************************************
  //2.设定通信停止位位数,此处设定为1位停止位
  UART1_CR3 = 0x00;
  //**************************************************
  //展开UART1_CR3赋值二进制数值为:0000 0000 
  //含义:保留位=0;必须保持清零
  //      LINEN=0;LIN模式被禁止
  //      STOP=00;配置为“00”,1个停止位
  //      CLKEN、CPOL、CPHA、LBCL这几位在UART3上不存在
  //*************************************************
  //3.配置通信波特率参数,此处配置为9600bps(16MHz频率下)
  UART1_BRR2 = 0x03;
  UART1_BRR1 = 0x68;
  //4.使能发送和接收功能
//  UART1_CR2 = 0x0C;
  UART1_CR2 = 0x2C;
  //**************************************************
  //展开UART1_CR2赋值二进制数值为:0010 1100 
  //含义:TIEN=0;发送中断被禁止
  //     TCIEN=0;发送中断完成被禁止
  //      RIEN=1;接收中断开启
  //      ILIEN=0;IDLE中断被禁止
  //      TEN=1;发送功能使能
  //      REN=1;接收功能使能
  //      RWU=0;(UART模式)正常工作模式
  //      PIEN=0;未发送断开字符
  //*************************************************
}
//测试代码
void UART1_Module(void)
{
   u8 databuf[] = "****************************************\n";
   UART1_SendString(databuf);
   printf("Clichong\n");
   UART1_SendString(databuf);
}
目录
相关文章
|
6月前
|
数据采集 数据处理 C语言
单片机:探索其原理、应用与编程实践
单片机:探索其原理、应用与编程实践
98 1
【单片机】简单的自定义延时程序设计(代码演示)
【单片机】简单的自定义延时程序设计(代码演示)
|
6月前
|
监控 Linux 定位技术
Linux应用开发基础知识——串口应用编程(十一)
Linux应用开发基础知识——串口应用编程(十一)
156 0
Linux应用开发基础知识——串口应用编程(十一)
|
6月前
|
数据格式
串口通信知识点总结
串口通信知识点总结
101 0
|
芯片
矩阵键盘原理及程序设计
本文详细介绍了矩阵键盘是什么,主要应用场景,替代品,矩阵键盘的优缺点以及矩阵键盘的按键检测方法。最后附上了以STM32F103系列芯片为例的C程序。
420 2
|
传感器 算法 IDE
LabVIEW和Arduino的巧妙结合(基础篇—1)
本专栏使用的单片机为:Arduino(本系列专栏使用Arduino UNO控制器),主要原因在于,Arduino简单易上手,老少皆宜,受众面广泛,使用Arduino作为下位机,LabVIEW作为上位机,独立开发者可以快捷开发出一套软硬件联控的演示系统。
|
缓存
蓝桥杯之单片机学习(十一)——串口通信的基本原理与应用
蓝桥杯之单片机学习(十一)——串口通信的基本原理与应用
400 0
蓝桥杯之单片机学习(十一)——串口通信的基本原理与应用
蓝桥杯之单片机学习(十二)——串口通信进阶应用案例解析
蓝桥杯之单片机学习(十二)——串口通信进阶应用案例解析
278 0
蓝桥杯之单片机学习(十二)——串口通信进阶应用案例解析
蓝桥杯之单片机学习(五)——独立按键的基本操作与扩展应用
蓝桥杯之单片机学习(五)——独立按键的基本操作与扩展应用
318 0
蓝桥杯之单片机学习(五)——独立按键的基本操作与扩展应用
|
监控 芯片 内存技术
通俗易懂的带你解读inout双向端口【Verilog高级教程】
通俗易懂的带你解读inout双向端口【Verilog高级教程】
通俗易懂的带你解读inout双向端口【Verilog高级教程】
下一篇
无影云桌面