文章目录
需要掌握:
1.波特率-WIKI
2.STM32F10xxx中文参考手册-25章(这个手册对于stm32的学习极其重要!!!)
1.基于库函数编程和基于寄存器编程的区别
库函数是厂商为了简化程序的开发,降低入门门槛,将代码一层层进行封装直接调用,相当于对寄存器操作的封装,使用起来简单,对底层硬件的掌握要求不高,使用的时候直接调用库函数就可以了。但同时也存在代码复杂,编译时间长的问题。
而寄存器编程则更加原始,更加底层,更加高效简洁。对底层知识要求更高,代码编译难度更高更复杂。操作寄存器,你必须明白每个数据位的物理意义,直观而且明确。上手更难,对知识储备的要求更高。
最好是能了解寄存器编程,可以针对自己编程的需要改写库函数。
2.波特率
其中I 为传信率,S 为波特率,N 为每个符号负载的信息量,而以比特为单位。
因此只有在每个符号只代表一个比特信息的情况、或一些简单的调制方式下,例如基带二进制信号、或Bell 103或CCITT V.21(左列两种均为FSK)调制方式等,波特率与比特率才在数值上相等,但是它们的意义并不相同。
在电子通信领域,波特(Baud)即调制速率,指的是有效数据讯号调制载波的速率,即单位时间内载波调制状态变化的次数。它是对符号传输速率的一种度量,1波特即指每秒传输1个符号,而透过不同的调制方式,可以在一个码元符号上负载多个bit位信号。
“波特”(Baud)本身已是速率,所以不需要写成Baud Rate(Rate 是赘字)。
单位“波特”本身就已经是代表每秒的调制数,以“波特每秒”(Baud per second)为单位是一种常见的错误,但是在一般中文口语化的沟通上还是常以“波特率”来描述“波特”(Baud)。
波特率有时候会同比特率混淆
实际上后者是对信息传输速率(传信率)的度量。波特率可以被理解为单位时间内传输符号的个数(传符号率)
3.为什么单片机需要使用中断
通过串口的中断函数可以实现在串口通信的一帧数据传送完成后实现你想要的功能。
不然单片机就会一直工作在传输数据的状态没办法干别的事。
比方说你想看看一帧的数据是否完成的传送,可以利用串口通信的中断函数去验证。
一、STM32的USART窗口通讯程序
要求
1)设置波特率为115200,1位停止位,无校验位。
2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。
3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送。
硬件介绍
本人使用的是野火的野火MINI开发板,芯片是STM32F103RCT6
很方便的一点就是电脑安装CH340驱动后就可以实现USB转串口,用USB线就能实现串口通讯,不需要额外的购置串口线或者USB转串口的配件
USART介绍
通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。 它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据 组织)SIRENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。 使用多缓冲器配置的DMA方式,可以实现高速数据通信。
寄存器标志位
状态SR常用:
数据DR常用:
波特率BRR常用:
还有
主要是发送/接受使能和中断使能(Enable)
串口初始化需要设置的(以本实验代码位例子):
步骤实例:
1. 串口时钟使能
2.忽略
3.GPIO端口模式设置
GPIO端口模式设置可以在上面提到的手册的8.1.11 查表
输入模式相关:上拉输入、下拉输入、浮空输入、模拟输入的区别
这里注意到GPIO_TX的模式设置的是推挽复用,原因如下:
因为是串口不在时普通的IO口所以复用,
因为没接上拉电阻所以推挽。
因为TX为发送数据端口所以输出。
这样,输出口的GPIO设置完成
接收口的GPIO,注意这里是pin_10,TX是pin_9,
接收口用到是浮空/带上拉 输入
4.串口参数初始化
//USART相关寄存器设置
void User_USART_Config(void)
{
USART_InitTypeDef USART_Config;
//使能USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//初始化USART_InitTypeDef结构体
USART_Config.USART_BaudRate = 115200; //波特率
USART_Config.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制(此处不用)
USART_Config.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //发送和接收使能设置
USART_Config.USART_Parity = USART_Parity_No; //奇偶校验位 (此处不用)
USART_Config.USART_StopBits = USART_StopBits_1; //停止位
USART_Config.USART_WordLength = USART_WordLength_8b; //字长(可以是8或9位)
//设置USART1对应的寄存器
USART_Init(USART1, &USART_Config);
//使能USART1 数据接收RXEN中断寄存器,即接收数据寄存器有数据可读时,RXEN寄存器产生中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//使能串口USART1,使其进行工作
USART_Cmd(USART1, ENABLE);
}
USART_Init函数第二个参数是结构体类型指针,所有必须先定义一个结构体
2/3步无先后顺序
我们因为需要的是全双工的通讯
所有这里3的mode同时使能了发送TX和接收口RX
5.开启中断并且初始化NVIC
开启接收中断
ITConfig:中断使能函数
USART_IT_RXNE函数在上文已经说过了,为读取器寄存非空函数
跟GPIO类似初始化入口函数Init
并设置优先级组
初始化结构体
6.使能串口
使用Cmd函数
7.编写中断处理函数
这里我们要求中断发生的条件是接收到了数据
中断发生后,判断接收到的字符是否为“Stop Stm32”
如果是,则停止发送,如果不是则继续发送
8.串口数据收发
这里我不需要任何中断服务,就把原程序的回显函数删掉了
9.串口传输状态获取
主函数
int main(void)
{
DEBUG_UART_Config();
//USART_SendData(DEBUG_USARTx, 'a');
// printf->fputc->USART_SendData->µçÄÔµÄÉÏλ»ú
while(1)
{
uint8_t ucTemp;
uint8_t StopFlag[]="stop,stm32";
uint16_t len,i;
int Flag_s=1;
/************************/
uint8_t flag1=0;
delay(100000);
printf("hello windows!\r\n");
/****************************/
if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
{
len=DEBUG_USARTx->DR & (uint16_t)0x01FF;
ucTemp = USART_ReceiveData(DEBUG_USARTx);
for(i=0;i<len;i++)
{
if(StopFlag[i]==ucTemp)Flag_s=0;
if(BeginFlag[i]==ucTemp)Flag_s=0;
}
if(Flag_s==1)
{
flag1=1;
}
}
if(flag1==1)break;
}
}
调试效果:
参考博客及总结
1.串口调试器使用的时候需要将串口程序下载器关闭,否则通讯会出错
2.while循环的时候可以使用delay函数延时发送