实验四 串口通信实验
一、实验目的
1、掌握基于固件库进行串口通信编程的方法
二、实验内容
任务1:基于固件库编程使用USART通信从上位机给stm32发送信息,再把信息通过USART发送回上位机在串口调试助手中显示。要求:数据发送和接受过程通过中断服务函数实现。
任务2(选做):软件电路仿真方法:使用stm32发送字符到proteus串口元件并在数码管中显示出。proteus仿真电路图可在学习通资料中下载获得。需要使用虚拟串口通信;需要安装的软件有:虚拟串口软件,可在学习通中下载。
任务3(选做):实现教材中6.5.2 串行异步通信应用实例2:上位机控制LED亮灭。具体任务要求和流程图如教材所示。
三、预备知识
1、基于STM32固件库进行编程的方法
2、STM32串口通信编程方法
四、实验设备
1. 硬件环境配置
计算机:Intel(R) Pentium(R) 及以上;
内存:1GB及以上;
实验设备:嵌入式开发平台,USB转串口数据线;
2. 软件环境配置
操作系统:Microsoft Windows XP Professional Service Pack 2;
集成开发环境:Keil μVision5 IDE;
五、实验过程
1.电路设计
2.实现通信
3.串口初始化过程
串口初始化过程通常包括以下几个步骤:
1. 选择串口模块:在MCU中,通常有多个串口模块可以选择,需要根据具体的应用需求来选择合适的串口模块。
2. 配置GPIO引脚:在使用串口时,需要将相应的GPIO引脚设置为串口功能模式,以便能够进行数据传输。
3. 配置串口参数:包括波特率、数据位、停止位、奇偶校验位等参数。根据需要的传输速率和通信协议来选择合适的参数。
4. 使能串口模块:使用串口控制寄存器来使能串口模块,以便能够进行数据传输。
5. 编写中断服务函数:在使用中断方式进行串口数据传输时,需要编写相应的中断服务函数。
6. 初始化DMA(可选):在使用DMA方式进行串口数据传输时,需要进行DMA初始化。
7. 发送和接收数据:使用串口发送和接收数据的函数来进行数据传输。
4.软件设计及代码
- 主函数程序
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
int main(void)
{
u16 t;
u16 len;
u16 times=0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //LED端口初始化
KEY_Init(); //初始化与按键连接的硬件接口
while(1)
{
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
printf("\r\n您发送的消息为:\r\n\r\n");
for(t=0;t<len;t++)
{
USART_SendData(USART1, USART_RX_BUF[t]);//向串口1发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
printf("\r\n\r\n");//插入换行
USART_RX_STA=0;
}
if(USART_RX_BUF[0]=='1')LED0=!LED0;
delay_ms(10);
}
}
- 串口初始化
void uart_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
- 中断服务函数
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}