F407+ESP8266+MQTT+AliIoT(三)——TIM7+USART3的使用

F407+ESP8266+MQTT+AliIoT(三)——TIM7+USART3的使用

简介

在项目里,串口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
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值