文章内容
:
在STM32 的 USART 串口通讯—汇编输出 hello windows!的基础上,学习 stm32 串口中断,采用串口中断方式重做汇编输出 hello windows!要求:
1)设置波特率为115200,1 位停止位,无校验位。
2)STM32 系统给上位机( win10 )连续发送“hello windows!”。win10 采用“串口助手”工具接收。
3)当上位机给 stm32 发送 “ stop,stm32! ” 后,STM32 停止发送。
目录
1 USART 接发通信
1.1 任务说明
在上一篇文章中,我们实现了 STM32 将数据传输给主机,我们不仅仅可以将数据发送到串口调试助手,我们还可以在串口调试助手发送数据给 STM32,控制器程序根据接收到的数据进行下一步工作。
首先,我们来编写一个程序实现 STM32 开发板与电脑通信,在开发板上电时通过 USART 发送一串字符串给电脑,然后开发板进入中断接收等待状态,如果
电脑有发送数据过来,开发板就会产生中断
,我们在中断服务函数接收数据,并马上把数据返回发送给电脑
。
1.2 USART 控制器
SART 有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等等。使用 USART 之前需要向 USART_CR1 寄存器的 UE 位置 1 使能 USART,UE 位用来开启供给给串口的时钟。发送或者接收数据字长可选 8 位或 9 位,由 USART_CR1 的 M 位控制。
1.2.1 发送器
当发送使能位 TE 置 1 之后,发送器开始会先发送一个空闲帧(一个数据帧长度的高电平),接下来就可以往 USART_DR 寄存器写入要发送的数据。在写入最后一个数据后,需要等待 USART 状态寄存器(USART_SR)的 TC 位为 1,表示数据传输完成,如果 USART_CR1 寄存器的 TCIE 位置 1,将产生中断。
字符发送时序图:
1.2.2 接收器
如果将 USART_CR1 寄存器的 RE 位置 1,使能 USART 接收,使得接收器在 RX 线开始搜索起始位。在确定到起始位后就根据 RX 线电平状态把数据存放在接收移位寄存器内。接收完成后就把接收移位寄存器数据移到 RDR 内,并把 USART_SR 寄存器的 RXNE 位置 1,同时如果 USART_CR2 寄存器的 RXNEIE 置 1 的话可以产生中断。
2 串口中断实验过程
2.1 实验准备
- 环境:Keil 5( win10 )
- 工具:烧录软件 mcuisp (提取码:cyuu)、串口调试助手(提取码:luha)
- 硬件:STM32F103C8 开发板、USB转TTL 模块、导线若干
- 代码:根据指南者配套开发的程序再修改得来提取码:luha
2.2 代码分析
全部代码可以从上面的链接里获取。
在编写代码时,只需要对三个文件进行修改即可,其他都是库文件,不用更改。这里做简单分析:
- GPIO 和 USART 宏定义
/*串口1-USART1 */
#define DEBUG_USARTx USART1 //定义串口一
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200 //设置波特率为 115200
/*USART GPIO 引脚宏定义*/
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10
#define DEBUG_USART_IRQ USART1_IRQn
#define DEBUG_USART_IRQHandler USART1_IRQHandler
使用宏定义方便程序移植和升级。
这里我们使用 USART1,设定波特率为115200,选定 USART 的 GPIO 为 PA9 和 PA10。
-
中断控制器 NVIC 配置与字符发送
这两个函数的具体解释在代码中也已标注,不再过多赘述。 -
USART 中断服务函数
// 串口中断服务函数
void DEBUG_USART_IRQHandler(void)
{
uint8_t ucTemp;
//串口一接收中断
if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
{
//获取接收到的数据
ucTemp = USART_ReceiveData(DEBUG_USARTx);
//如果接收标志为 0 ,则执行下面的部分
if((USART_RX_FLAG & 0x8000) == 0)
{
//接收到了0x0d
if(USART_RX_FLAG & 0x4000)
{
//接收错误,重新开始
if(ucTemp != 0x0a)
USART_RX_FLAG=0;
//接收完成
else
USART_RX_FLAG |= 0x8000;
}
//还未接收到0x0d
else
{
//接收到回车
if(ucTemp == 0x0d)
{
USART_RX_FLAG |= 0x4000;
}
else
{
USART_RX_BUF[USART_RX_FLAG & 0x3FFF] = ucTemp;
USART_RX_FLAG++;
//接收数据错误,重新开始接收
if(USART_RX_FLAG > 99)
USART_RX_FLAG = 0;
}
}
}
}
}
USART_GetITStatus 函数与 USART_GetFlagStatus 函数类似用来获取标志位状态,但 USART_GetITStatus 函数是专门用来获取中断事件标志的,并返回该标志位状态。使用 if语句来判断是否是真的产生 USART数据接收这个中断事件,如果是真的就使用 USART 数据读取函数 USART_ReceiveData 读取数据到指定存储区。然后再调用 USART 数据发送函数 USART_SendData 把数据又发送给串口。
- 延时函数
//毫秒级的延时函数
void delay_ms(uint16_t delay_ms)
{
volatile unsigned int num;
for (num = 0; num < delay_ms; num++)
{
delay_us(1000);
}
}
- 发送数据函数
//连续发送数据
void Usart_SendString(void)
{
uint8_t i = 0;
while(1)
{
if(USART_RX_FLAG & 0x8000)
{
// 获取接收到的数据长度
len = USART_RX_FLAG & 0x3FFF;
Usart_SendStr(DEBUG_USARTx, "\n");
for(i=0; i<len;i++)
{
// 向串口发送数据
USART_SendData(DEBUG_USARTx, USART_RX_BUF[i]);
//等待发送结束
while(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TC)!=SET);
}
Usart_SendStr(DEBUG_USARTx, "\n\n");
//比较字符串
if(strcmp((char *)USART_RX_BUF,"stop,stm32!")==0)
{
Usart_SendStr(DEBUG_USARTx, "stm32已停止发送!");
break;//退出循环
}
//初始化
USART_RX_FLAG=0;
memset(USART_RX_BUF,0,sizeof(USART_RX_BUF));
}
else
{
//循环发送数据
Usart_SendStr(DEBUG_USARTx, "hello windows!\n");
delay_ms(800);
}
}
}
在发送数据中,添加了接收数据语句,当 STM32 收到上位机发来的数据后,它会将数据回传给串口,并结束发送。
- 主函数
int main(void)
{
USART_Config();
Usart_SendString(); //调用连续发送数据函数
return 0;
}
主函数什么都不做,只是静静地等待 USART 接收中断的产生,并在中断服务函数把数据回传。
2.3 编译形成 hex 文件
点击编译形成 hex 文件,警告可忽略。
2.4 串口中断通讯结果
- 硬件连接
只需要完成USB转TTL模块
和stm32f103c8t6
的连接。
GND-G
3V3-3.3
RXD-A9
TXD-A10
- 烧录
使用 mcuisp 软件打开 hex 文件,将板子的 boot0 置 1,boot1 置 0
,成功烧写进 STM32F103C8T6 板子中。
- 串口调试效果
烧录成功后,切记要将板子断电(直接拔掉),将板子的boot0 置 0
,再上电。
设置好串口调试助手的各个参数,打开 hex 文件,如下图:
打开串口,并发送stop,stm32!
,效果如下:
3 总结
整篇文章的编写还是比较顺利的,许多代码都是库文件里的,需要编写的代码并不是很多。通过串口中断完成 STM32 与上位机的通讯,代码主要实现是在发送数据函数这里,在发送数据中,添加了接收数据语句,当 STM32 收到上位机发来的数据后,它会将数据回传给串口,并结束发送。
文章内容知识串口中断通讯的一个小例子,读者可以继续学习,下面附有学习资料。
4 参考资料
1、基于 stm32 的应用实例 —— USART 串口通讯(stm32 与主机通讯)
2、《零死角玩转STM32—F103指南者》第 21 章:USART串口通讯
提取码:luha
3、STM32串口通信USART学习笔记