一、應用簡介
本文介紹串口中斷接收不定長字串的方法,采用定時中斷給串口2的接收提供定時,再一次中斷內(1ms)接收資料的長度不變則認為接收完成,
board_uart.h
/**===========================================================================
@file board_uart.h
@brief 本檔案是用于串口驅動
@author 青梅煮久
@version r0.1
@date 2021/01/15
----------------------------------------------------------------------------
Remark: (備注描述)
串口2的接收驅動,接收不定長資料,
----------------------------------------------------------------------------
History
----------------------------------------------------------------------------
<Date> | <Version> | <Author> | <Description>
-------------|-----------|----------------|---------------------------------
2021/01/15 | r0.1 | 青梅煮久 | 創建
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
============================================================================*/
#ifndef __BOARD_UART_H
#define __BOARD_UART_H
/*********************************************************************
* INCLUDES
*/
#include "stm32f10x.h"
/*********************************************************************
* DEFINITIONS
*/
#define MAX_LENGTH 1024
/*********************************************************************
* GLOBAL VARIABLES
*/
extern uint8_t g_rxFlag;
extern uint8_t g_rxFinish;
extern uint16_t g_receiveLength;
extern uint16_t g_currentLength;
extern char g_receiveBuffer[MAX_LENGTH];
extern char g_manageBuffer[MAX_LENGTH];
extern uint8_t g_receiveData[MAX_LENGTH];
/*********************************************************************
* API FUNCTIONS
*/
void BASIC_UART2_NVIC_Config(void);
void USART2_Config(void);
#endif /* __BOARD_UART_H */
board_uart.c
/**===========================================================================
@file board_uart.c
@brief 本檔案是用于串口驅動
@author 青梅煮久
@version r0.1
@date 2021/01/15
----------------------------------------------------------------------------
Remark: (備注描述)
串口2的接收驅動,接收不定長資料,
----------------------------------------------------------------------------
History
----------------------------------------------------------------------------
<Date> | <Version> | <Author> | <Description>
-------------|-----------|----------------|---------------------------------
2021/01/15 | r0.1 | 青梅煮久 | 創建
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
============================================================================*/
/*********************************************************************
* INCLUDES
*/
#include "main.h"
#include "stdio.h"
#include "board_uart.h"
#include "board_timer.h"
/*********************************************************************
* GLOBAL VARIABLES
*/
uint8_t g_rxFlag = 0; // 接收標志0-未接受 1-正在接收
uint8_t g_rxFinish = 0; // 接收結束標志0-不存在接收完成資料 1-存在接收完成資料(main函式處理)
uint16_t g_receiveLength = 0; // 接收長度
uint16_t g_currentLength = 0; // 計時長度,定時器觸發時的接收長度,定時器到時只需比較接收長度和計時長度就可知道接收完成,
char g_receiveBuffer[MAX_LENGTH]; // 接收陣列,接收16進制字串,如'5','A','A','5','F','F'
char g_manageBuffer[MAX_LENGTH]; // 處理陣列,接收完成后接收陣列內容放到,重置接收陣列
uint8_t g_receiveData[MAX_LENGTH]; // 接收位元組,接收16進制字串轉位元組流,如0x5A,0xA5,0xFF
/*********************************************************************
* LOCAL VARIABLES
*/
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief NVIC初始化
@param 無
@return 無
*/
void BASIC_UART2_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中斷控制器組選擇 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**
@brief 串口初始化
@param 無
@return 無
*/
void USART2_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打開串口 GPIO 的時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
//以下為串口2配置
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_USART2,ENABLE);
/*
* USART1_TX -> PA2 , USART1_RX -> PA3
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位資料
USART_InitStructure.USART_StopBits = USART_StopBits_1;//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(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_Cmd(USART2, ENABLE);
USART_ClearITPendingBit(USART2, USART_IT_TC);//清除中斷TC位
}
/**
@brief 串口2中斷處理
@param 無
@return 無
*/
void USART2_IRQHandler(void)
{
char temp;
if(USART_GetITStatus(USART2, USART_IT_RXNE))
{
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
temp = USART_ReceiveData(USART2);
if(g_receiveLength == MAX_LENGTH)
{
return;
}
if(!g_rxFlag)
{
g_rxFlag = 1;
// 開定時器
g_currentLength = 0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
}
g_receiveBuffer[g_receiveLength++] = temp;
}
}
board_timer.h
/**===========================================================================
@file board_timer.h
@brief 本檔案是基本定時器TIM6的驅動
@author 青梅煮久
@version r0.1
@date 2021/01/15
----------------------------------------------------------------------------
Remark: (備注描述)
給串口2的接收提供定時,再一次中斷內(1ms)接收資料的長度不變則認為接收
完成,
----------------------------------------------------------------------------
History
----------------------------------------------------------------------------
<Date> | <Version> | <Author> | <Description>
-------------|-----------|----------------|---------------------------------
2021/01/15 | r0.1 | 青梅煮久 | 創建
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
============================================================================*/
#ifndef __BOARD_TIMER_H
#define __BOARD_TIMER_H
/*********************************************************************
* INCLUDES
*/
#include "stm32f10x.h"
/*********************************************************************
* API FUNCTIONS
*/
void BASIC_TIM_NVIC_Config(void);
void BASIC_TIM_Config(void);
#endif /* __BOARD_TIMER_H */
board_timer.c
/**===========================================================================
@file board_timer.c
@brief 本檔案是基本定時器TIM6的驅動
@author 青梅煮久
@version r0.1
@date 2021/01/15
----------------------------------------------------------------------------
Remark: (備注描述)
給串口2的接收提供定時,再一次中斷內(1ms)接收資料的長度不變則認為接收
完成,
----------------------------------------------------------------------------
History
----------------------------------------------------------------------------
<Date> | <Version> | <Author> | <Description>
-------------|-----------|----------------|---------------------------------
2021/01/15 | r0.1 | 青梅煮久 | 創建
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
============================================================================*/
/*********************************************************************
* INCLUDES
*/
#include "main.h"
#include "board_timer.h"
#include "board_uart.h"
#define BASIC_TIM_IRQHandler TIM6_IRQHandler
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief NVIC初始化(使用TIM6基本定時器)
@param 無
@return 無
*/
void BASIC_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 設定中斷組為 2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**
@brief 定時器中斷配置(使用TIM6基本定時器)
@param 無
@return 無
*/
void BASIC_TIM_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/*
可以從上圖看出基本定時器和通用定時器使用APB1總線,
高級定時器使用APB2總線,
*/
// 開啟定時器時鐘,即內部時鐘 CK_INT=72M
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
/*
預分頻將輸入時鐘頻率按1~65536之間的值任意分頻,分頻值決定了計數頻率,
計數值為計數的個數,當計數暫存器的值達到計數值時,產生溢位,發生中斷,
如系統時鐘為72MHz,預分頻 TIM_Prescaler = 71,
計數值 TIM_Period = 1000,
則 TIM_Period * (TIM_Prescaler + 1) / 72000000 = 0.001,
即每1ms產生一次中斷,
*/
// 自動重裝載暫存器周的值(計數值)
TIM_TimeBaseStructure.TIM_Period = 1000;
// 累計 TIM_Period 個頻率后產生一個更新或者中斷
// 時鐘預分頻數為 71,
// 則驅動計數器的時鐘 CK_CNT = CK_INT / (71+1)=1M
TIM_TimeBaseStructure.TIM_Prescaler = 71;
// 時鐘分頻因子 ,基本定時器沒有,不用管
//TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 計數器計數模式,基本定時器只能向上計數,沒有計數模式的設定
//TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重復計數器的值,基本定時器沒有,不用管
//TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
/*
完成時基設定
*/
// 初始化定時器
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
/*
為了避免在設定時進入中斷,這里需要清除中斷標志位,
如果是向上計數模式(基本定時器采用向上計數),
則采用函式 TIM_ClearFlag(TIM6, TIM_FLAG_Update),
清除向上溢位中斷標志,
*/
// 清除計數器中斷標志位
TIM_ClearFlag(TIM6, TIM_FLAG_Update);
// 使能計數器
TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
// 開啟計數器
TIM_Cmd(TIM6, ENABLE);
// 暫時關閉定時器的時鐘,等待使用
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, DISABLE);
}
/**
@brief 定時器中斷(使用TIM6基本定時器)
@param 無
@return 無
*/
void BASIC_TIM_IRQHandler(void)
{
if(TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM6, TIM_FLAG_Update);
if(g_currentLength == g_receiveLength)
{
// 接收完成
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, DISABLE);
printf("接收完成\n");
memcpy(g_manageBuffer, g_receiveBuffer, g_receiveLength);
g_rxFlag = 0;
g_receiveLength = 0;
memset(g_receiveBuffer, 0, sizeof(g_receiveBuffer));
g_rxFinish = 1;
}
else
{
g_currentLength = g_receiveLength;
}
}
}
//使用微庫(平臺式keil-MDK),點擊“魔術棒” Target標簽下有個Use MicroLIB—勾選
// 重定向c庫函式printf到USART2
/**
@brief 重定向c庫函式printf到USART2
@param 無
@return 無
*/
int fputc(int ch, FILE *f)
{
USART_SendData(USART2,(u8)ch);
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
return (ch);
}
main.c
int main(void)
{
BASIC_TIM_NVIC_Config();
BASIC_TIM_Config();
BASIC_UART2_NVIC_Config();
USART2_Config();
while(1)
{
// 串口資料校驗
if(g_rxFinish == 1)
{
printf("有資料待處理\n");
memset(g_manageBuffer, 0x00, sizeof(g_manageBuffer));
g_rxFinish = 0;
}
}
}
? 由 青梅煮久 寫于 2021 年 01 月 15 日
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/249543.html
標籤:其他
上一篇:Hello CSDN
