簡介
在項目裏,串口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