三种不同串口介绍
串口通信的设置的流程:
- 确定主时钟,并进入串口初始化
此时如果选定HSI片内时钟可能会有误差,而HSE的精度可能会好一点
- 设置发送数据位数
- 设定发送数据校验位及校验方式
- 设定发送数据停止位位数
- 设定发送数据波特率
- 使能发送中断功能
此步也可以直接查询,无需使能中断,有中断就有中断服务函数
- 使能发送功能
- 发送单字节的数据
可以重定向,重新改写相关的函数就可以了
- 等待发送完毕
主要的寄存器:
- 帧结构如下图
- 如何配置数据位(帧结构的第二个部分)
- 如何配置校验位(帧结构的第三个部分)
校验位与数据帧格式说明
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; 校验中断被禁止 //*************************************************
- 如何设置停止位(帧结构的第三个部分)
UART1_CR3 = 0x00; //************************************************** //展开UART1_CR3赋值二进制数值为:0000 0000 //含义:保留位=0;必须保持清零 // LINEN=0;LIN模式被禁止 // STOP=00;配置为“00”,1个停止位 // CLKEN、CPOL、CPHA、LBCL这几位在UART3上不存在 //*************************************************
- 如何设置波特率
注意:BRR1寄存器的两个位不能同时为0,分配值不能小于16(0x000f),否则串口就不能使用,波特率失效
//配置通信波特率参数,此处配置为9600bps(16MHz频率下) UART1_BRR2 = 0x03; UART1_BRR1 = 0x68;
- 使能位的设定
//使能发送和接收功能 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三个位)
两种发送数据的方式:
- 第一种:利用指针偏移不断的将字符串输出
/****************************************************************/ //发送单字符函数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");
可见方法二比较方便,两种方法都可以输出信息。
- 接收数据的方式
/****************************************************************/ //接收单字符函数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); }