简介
在项目里,串口3用来和ESP8266进行通讯,使用定时器7来判断串口3的输入数据是否一帧结束。
定时器7设置为100ms中断,在中断处理函数中,标记一帧串口3数据结束,并关闭定时器。
串口3用来接收外设ESP8266发过来的数据,在中断中进行处理,同时参考串口1的代码,设计了u3_printf函数。
这部分可以参考《STM32F4开发指南-HAL库版本_V1.2》的第九章串口通信实验和第十三章定时器中断实验。
相关程序源码
啥也别说,直接上代码。
timer.c
#include "timer.h"
extern vu16 USART3_RX_STA;
TIM_HandleTypeDef TIM7_Handler; //定时器句柄
//定时器7配置预装载周期值
void TIM7_SetARR(u16 period)
{
TIM7->CNT = 0; //计数器清空
TIM7->ARR&=0x00; //先清预装载周期值为0
TIM7->ARR|= period;//更新预装载周期值
}
//通用定时器7中断初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器7!(定时器7挂在APB1上,时钟为HCLK/2)
void TIM7_Init(u16 arr,u16 psc)
{
__HAL_RCC_TIM7_CLK_ENABLE(); //使能TIM7时钟
TIM7_Handler.Instance=TIM7; //基本定时器7
TIM7_Handler.Init.Prescaler=psc; //分频系数
TIM7_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数器
TIM7_Handler.Init.Period=arr; //自动装载值
TIM7_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
HAL_TIM_Base_Init(&TIM7_Handler);
HAL_TIM_Base_Start_IT(&TIM7_Handler); //使能定时器7和定时器7更新中断:TIM_IT_UPDATE
HAL_NVIC_SetPriority(TIM7_IRQn,0,1); //设置中断优先级,抢占优先级0,子优先级1
HAL_NVIC_EnableIRQ(TIM7_IRQn); //开启ITM7中断
}
//定时器7中断服务函数
void TIM7_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM7_Handler);
}
//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&TIM7_Handler))//定时器7中断服务函数调用(GSM调用)
{
USART3_RX_STA|=1<<15; //标记接收完成
HAL_TIM_Base_Stop(&TIM7_Handler);//关闭定时器7
}
}
timer.h
#ifndef _TIMER_H
#define _TIMER_H
#include "sys.h"
extern TIM_HandleTypeDef TIM7_Handler; //定时器句柄
void TIM7_Init(u16 arr,u16 psc);
void TIM7_SetARR(u16 period);
#endif
usart.c
#include "usart3.h"
#include "delay.h"
#include "stdarg.h"
#include "stdio.h"
#include "string.h"
#include "timer.h"
//串口发送缓存区
__align(8) u8 USART3_TX_BUF[USART3_MAX_SEND_LEN]; //发送缓冲,最大USART3_MAX_SEND_LEN字节
#ifdef USART3_RX_EN //如果使能了接收
//串口接收缓存区
u8 USART3_RX_BUF[USART3_MAX_RECV_LEN]; //接收缓冲,最大USART3_MAX_RECV_LEN个字节.
UART_HandleTypeDef UART3_Handler; //UART句柄
u16 USART3_RX_STA=0;
//初始化IO,串口3
//bound:波特率
void uart3_init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟
__HAL_RCC_USART3_CLK_ENABLE(); //使能USART1时钟
//UART 初始化设置
UART3_Handler.Instance=USART3; //USART3
UART3_Handler.Init.BaudRate=bound; //波特率
UART3_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为8位数据格式
UART3_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位
UART3_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位
UART3_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
UART3_Handler.Init.Mode=UART_MODE_TX_RX; //收发模式
HAL_UART_Init(&UART3_Handler); //HAL_UART_Init()会使能UART3
GPIO_Initure.Pin=GPIO_PIN_10|GPIO_PIN_11; //PB10、PB11
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FAST; //高速
GPIO_Initure.Alternate=GPIO_AF7_USART3; //复用为USART3
HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化PB10,和PB11
__HAL_UART_DISABLE_IT(&UART3_Handler,UART_IT_TC);
#if USART3_RX_EN
__HAL_UART_ENABLE_IT(&UART3_Handler,UART_IT_RXNE); //开启接收中断
HAL_NVIC_EnableIRQ(USART3_IRQn); //使能USART1中断通道
HAL_NVIC_SetPriority(USART3_IRQn,2,3); //抢占优先级2,子优先级3
#endif
TIM7_Init(1000-1,9000-1); //重新设置为100ms中断
TIM7->CR1&=~(1<<0); //关闭定时器7
USART3_RX_STA=0; //清零
}
//timer=100ms
//通过判断接收连续2个字符之间的时间差不大于timer来决定是不是一次连续的数据.
//如果2个字符接收间隔超过timer,则认为不是1次连续数据.也就是超过timer没有接收到
//任何数据,则表示此次接收完毕.
//接收到的数据状态
//[15]:0,没有接收到数据;1,接收到了一批数据.
//[14:0]:接收到的数据长度
//串口3中断服务程序
void USART3_IRQHandler(void)
{
u8 Res;
if((__HAL_UART_GET_FLAG(&UART3_Handler,UART_FLAG_RXNE)!=RESET))
{
HAL_UART_Receive(&UART3_Handler,&Res,1,1000);
if((USART3_RX_STA&0x8000)==0) //接收完的一批数据,还没有被处理,则不再接收其他数据
{
if(USART3_RX_STA<USART3_MAX_RECV_LEN) //还可以接收数据
{
TIM7->CNT = 0; //计数器清空
if(USART3_RX_STA==0) //如果没有接收任何数据
{
TIM7->CR1|=1<<0; //开启定时器7
}
USART3_RX_BUF[USART3_RX_STA++]=Res; //记录接收到的值
}
else
{
USART3_RX_STA|=1<<15; //强制标记接收完成
}
}
}
HAL_UART_IRQHandler(&UART3_Handler);
}
//串口3,printf 函数
//确保一次发送数据不超过USART3_MAX_SEND_LEN字节
void u3_printf(char* fmt,...)
{
u16 i,j;
va_list ap;
va_start(ap,fmt);
vsprintf((char*)USART3_TX_BUF,fmt,ap);
va_end(ap);
i=strlen((const char*)USART3_TX_BUF);//此次发送数据的长度
for(j=0;j<i;j++) //循环发送数据
{
while((USART3->SR&0X40)==0); //循环发送,直到发送完毕
USART3->DR=USART3_TX_BUF[j];
}
}
//串口3,senddata 函数
//确保一次发送数据不超过USART3_MAX_SEND_LEN字节
void u3_send(u8* dat, u16 len)
{
u16 i,j;
i = len;
for(j=0;j<i;j++) //循环发送数据
{
while((USART3->SR&0X40)==0); //循环发送,直到发送完毕
USART3->DR=dat[j];
}
}
#endif
usart.h
#ifndef __USART3_H
#define __USART3_H
#include "sys.h"
#include "stdio.h"
#define USART3_MAX_RECV_LEN 400 //最大接收缓存字节数
#define USART3_MAX_SEND_LEN 400 //最大发送缓存字节数
#define USART3_RX_EN 1 //0,不接收;1,接收.
extern u8 USART3_RX_BUF[USART3_MAX_RECV_LEN]; //接收缓冲,最大USART3_MAX_RECV_LEN字节
extern u8 USART3_TX_BUF[USART3_MAX_SEND_LEN]; //发送缓冲,最大USART3_MAX_SEND_LEN字节
extern u16 USART3_RX_STA; //接收数据状态
extern UART_HandleTypeDef UART3_Handler;//UART句柄
void uart3_init(u32 bound); //串口3初始化
void u3_printf(char* fmt, ...);
void u3_send(u8* dat, u16 len);
#endif