实例介绍
【实例简介】使用DMA传送通过串口发送数据
【实例截图】
【核心代码】#include "stm32f1xx_hal.h"
#include "usart/bsp_usartx.h"
#include "led/bsp_led.h"
#include "string.h"
#include "GeneralTIM/bsp_GeneralTIM.h"
/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
#define SENDBUFF_SIZE 20 // 串口DMA发送缓冲区大小
/* 私有变量 ------------------------------------------------------------------*/
__IO uint8_t RxBuffer[50];
__IO uint8_t RX_5A_OK = 0; // 接收帧头0xA5标志
__IO uint8_t RX_A5_OK = 0; // 接收帧头0x5A标志
__IO uint8_t Rx_Cnt = 0; // 串口接收计数
__IO uint8_t aRxBufferTemp = 0; // 串口接收缓存
__IO uint8_t Rx_Finish = 0; // 串口数据接收完成标志
__IO uint16_t timer_count = 0; // 定时计数
uint8_t aRxBuffer; // 接收数据
uint8_t aTxBuffer[SENDBUFF_SIZE]; // 串口DMA发送缓冲区
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
void Fill_DATA(void);
void Analytical_Data(void);
/* 函数体 --------------------------------------------------------------------*/
/**
* 函数功能: 系统时钟配置
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 外部晶振,8MHz
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 9倍频,得到72MHz主时钟
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 系统时钟:72MHz
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB时钟:72MHz
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // APB1时钟:36MHz
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2时钟:72MHz
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
// HAL_RCC_GetHCLKFreq()/1000 1ms中断一次
// HAL_RCC_GetHCLKFreq()/100000 10us中断一次
// HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); // 配置并启动系统滴答定时器
/* 系统滴答定时器时钟源 */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* 系统滴答定时器中断优先级配置 */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/**
* 函数功能: 主函数.
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
int main(void)
{
/* 复位所有外设,初始化Flash接口和系统滴答定时器 */
HAL_Init();
/* 配置系统时钟 */
SystemClock_Config();
/* 初始化LED */
LED_GPIO_Init();
/* 基本定时器初始化:1ms中断一次 */
GENERAL_TIMx_Init();
/* 在中断模式下启动定时器 */
HAL_TIM_Base_Start_IT(&htimx);
/* 初始化串口并配置串口中断优先级 */
MX_USARTx_Init();
/* 使能接收,进入中断回调函数 */
HAL_UART_Receive_IT(&husartx,&aRxBuffer,1);
/* 无限循环 */
while (1)
{
/* 串口使用DMA传输数据不占用CPU,可以正常运行其他函数 */
Analytical_Data(); //调用数据解析函数
if(timer_count==1000) //串口定时发送数据
{
/* 计时清零 */
timer_count = 0;
/* 调用函数刷新数据 */
Fill_DATA();
/* 使用DMA传输数据到电脑端 */
HAL_UART_Transmit_DMA(&husartx,aTxBuffer, SENDBUFF_SIZE);
}
}
}
/**
* 函数功能: 填充要发送的数据
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void Fill_DATA(void)
{
/*填充将要发送的数据*/
aTxBuffer[0] = 0x5A;
aTxBuffer[1] = 0xA5;
aTxBuffer[2] = 0x10;
aTxBuffer[3] = 0x82;
aTxBuffer[4] = 0x00;
aTxBuffer[5] = 0x01;
aTxBuffer[6] = 0x02;
aTxBuffer[7] = 0x03;
aTxBuffer[8] = 0x04;
aTxBuffer[9] = 0x05;
aTxBuffer[10] = 0x06;
aTxBuffer[11] = 0x07;
aTxBuffer[12] = 0x08;
aTxBuffer[13] = 0x09;
aTxBuffer[14] = 0x0A;
aTxBuffer[15] = 0x0B;
aTxBuffer[16] = 0x0C;
aTxBuffer[17] = 0x0D;
aTxBuffer[18] = 0x0E;
aTxBuffer[19] = 0x0F;
}
/**
* 函数功能: 解析串口接收到的数据
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void Analytical_Data(void)
{
if(Rx_Finish)
{
if((RxBuffer[0]==0x06)&&(RxBuffer[1]==0x83)&&(RxBuffer[2]==0x00)
&&(RxBuffer[3]==0x00)&&(RxBuffer[4]==0x01)&&(RxBuffer[5]==0x00))
{
if(RxBuffer[6]==0x00)
{
LED1_TOGGLE;
}
if(RxBuffer[6]==0x01)
{
LED2_TOGGLE;
}
}
Rx_Finish = 0;
}
}
/**
* 函数功能: 串口接收完成回调函数
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
if(UartHandle->Instance==USART1)
{
aRxBufferTemp = aRxBuffer;
if(RX_5A_OK)
{
if(RX_A5_OK)
{
RxBuffer[Rx_Cnt] = aRxBufferTemp;
Rx_Cnt ;
if(Rx_Cnt == RxBuffer[0] 1) //接收完成
{
RX_5A_OK = 0;
RX_A5_OK = 0;
Rx_Finish = 1;
}
}
else
{
if(aRxBufferTemp == 0xA5)
{
RX_A5_OK = 1;
Rx_Cnt = 0;
}
}
}
else
{
if(aRxBufferTemp == 0x5A)
{
RX_5A_OK = 1;
}
}
HAL_UART_Receive_IT(&husartx,&aRxBuffer,1); //开启下一次接收中断
}
}
/**
* 函数功能: 非阻塞模式下定时器的回调函数
* 输入参数: htim:定时器句柄
* 返 回 值: 无
* 说 明: 无
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
timer_count ;
}
【实例截图】
【核心代码】#include "stm32f1xx_hal.h"
#include "usart/bsp_usartx.h"
#include "led/bsp_led.h"
#include "string.h"
#include "GeneralTIM/bsp_GeneralTIM.h"
/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
#define SENDBUFF_SIZE 20 // 串口DMA发送缓冲区大小
/* 私有变量 ------------------------------------------------------------------*/
__IO uint8_t RxBuffer[50];
__IO uint8_t RX_5A_OK = 0; // 接收帧头0xA5标志
__IO uint8_t RX_A5_OK = 0; // 接收帧头0x5A标志
__IO uint8_t Rx_Cnt = 0; // 串口接收计数
__IO uint8_t aRxBufferTemp = 0; // 串口接收缓存
__IO uint8_t Rx_Finish = 0; // 串口数据接收完成标志
__IO uint16_t timer_count = 0; // 定时计数
uint8_t aRxBuffer; // 接收数据
uint8_t aTxBuffer[SENDBUFF_SIZE]; // 串口DMA发送缓冲区
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
void Fill_DATA(void);
void Analytical_Data(void);
/* 函数体 --------------------------------------------------------------------*/
/**
* 函数功能: 系统时钟配置
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 外部晶振,8MHz
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 9倍频,得到72MHz主时钟
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 系统时钟:72MHz
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB时钟:72MHz
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // APB1时钟:36MHz
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2时钟:72MHz
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
// HAL_RCC_GetHCLKFreq()/1000 1ms中断一次
// HAL_RCC_GetHCLKFreq()/100000 10us中断一次
// HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); // 配置并启动系统滴答定时器
/* 系统滴答定时器时钟源 */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* 系统滴答定时器中断优先级配置 */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/**
* 函数功能: 主函数.
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
int main(void)
{
/* 复位所有外设,初始化Flash接口和系统滴答定时器 */
HAL_Init();
/* 配置系统时钟 */
SystemClock_Config();
/* 初始化LED */
LED_GPIO_Init();
/* 基本定时器初始化:1ms中断一次 */
GENERAL_TIMx_Init();
/* 在中断模式下启动定时器 */
HAL_TIM_Base_Start_IT(&htimx);
/* 初始化串口并配置串口中断优先级 */
MX_USARTx_Init();
/* 使能接收,进入中断回调函数 */
HAL_UART_Receive_IT(&husartx,&aRxBuffer,1);
/* 无限循环 */
while (1)
{
/* 串口使用DMA传输数据不占用CPU,可以正常运行其他函数 */
Analytical_Data(); //调用数据解析函数
if(timer_count==1000) //串口定时发送数据
{
/* 计时清零 */
timer_count = 0;
/* 调用函数刷新数据 */
Fill_DATA();
/* 使用DMA传输数据到电脑端 */
HAL_UART_Transmit_DMA(&husartx,aTxBuffer, SENDBUFF_SIZE);
}
}
}
/**
* 函数功能: 填充要发送的数据
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void Fill_DATA(void)
{
/*填充将要发送的数据*/
aTxBuffer[0] = 0x5A;
aTxBuffer[1] = 0xA5;
aTxBuffer[2] = 0x10;
aTxBuffer[3] = 0x82;
aTxBuffer[4] = 0x00;
aTxBuffer[5] = 0x01;
aTxBuffer[6] = 0x02;
aTxBuffer[7] = 0x03;
aTxBuffer[8] = 0x04;
aTxBuffer[9] = 0x05;
aTxBuffer[10] = 0x06;
aTxBuffer[11] = 0x07;
aTxBuffer[12] = 0x08;
aTxBuffer[13] = 0x09;
aTxBuffer[14] = 0x0A;
aTxBuffer[15] = 0x0B;
aTxBuffer[16] = 0x0C;
aTxBuffer[17] = 0x0D;
aTxBuffer[18] = 0x0E;
aTxBuffer[19] = 0x0F;
}
/**
* 函数功能: 解析串口接收到的数据
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void Analytical_Data(void)
{
if(Rx_Finish)
{
if((RxBuffer[0]==0x06)&&(RxBuffer[1]==0x83)&&(RxBuffer[2]==0x00)
&&(RxBuffer[3]==0x00)&&(RxBuffer[4]==0x01)&&(RxBuffer[5]==0x00))
{
if(RxBuffer[6]==0x00)
{
LED1_TOGGLE;
}
if(RxBuffer[6]==0x01)
{
LED2_TOGGLE;
}
}
Rx_Finish = 0;
}
}
/**
* 函数功能: 串口接收完成回调函数
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
if(UartHandle->Instance==USART1)
{
aRxBufferTemp = aRxBuffer;
if(RX_5A_OK)
{
if(RX_A5_OK)
{
RxBuffer[Rx_Cnt] = aRxBufferTemp;
Rx_Cnt ;
if(Rx_Cnt == RxBuffer[0] 1) //接收完成
{
RX_5A_OK = 0;
RX_A5_OK = 0;
Rx_Finish = 1;
}
}
else
{
if(aRxBufferTemp == 0xA5)
{
RX_A5_OK = 1;
Rx_Cnt = 0;
}
}
}
else
{
if(aRxBufferTemp == 0x5A)
{
RX_5A_OK = 1;
}
}
HAL_UART_Receive_IT(&husartx,&aRxBuffer,1); //开启下一次接收中断
}
}
/**
* 函数功能: 非阻塞模式下定时器的回调函数
* 输入参数: htim:定时器句柄
* 返 回 值: 无
* 说 明: 无
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
timer_count ;
}
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论