完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本程序开始之前已经开通了DMA的ADC通道
1、建立工程后,依次点击如图1、2、3、4、5 2、波特率选择9600,也可以选别的,能满足需求的波特率尽可能小,越小越稳定 3.1、开启DMA,添加Tx发送信息3.2、 同样的方法,添加Rx接收信息 4、选择DMA优先级,如图,优先级数字越小,优先级程度越高 5.1、由于使用485硬件发送与接收,因此使用一个IO控制硬件的收发功能,高电平时为发送,低电平是为接收模式,所有只有发送的时候是高电平,其余皆为低电平,我选择的IO是PTA11 5.1.2、依次单机1、2 5.1.2、依次单机如图所示,由于硬件隔离电路问题选择了开漏模式,如果没有隔离可以选择推挽模式加上拉电阻,速度选择高速模式5.2、完成后代码生成,并打开代码 6、在“main.h”中添加代码,位置如图 6.1、找到宏定义 /* Exported macro ------------------------------------------------------------*/ /* USER CODE BEGIN EM */ /* USER CODE END EM */ 添加代码 宏定义 接收到的数据长度BUFFER_SIZE 小于 100 /* Exported macro ------------------------------------------------------------*/ /* USER CODE BEGIN EM */ #define BUFFER_SIZE 100 /* USER CODE END EM */ 6.2、找到代码 /* Private defines -----------------------------------------------------------*/ /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ 添加全局变量,extern是全局变量定义,就是定义的数组整个工程都可以用 /* Private defines -----------------------------------------------------------*/ /* USER CODE BEGIN Private defines */ extern unsigned int timen;//系统运行绝对时钟,从系统运行开始计时,每1ms自加一次 extern unsigned short ADC[10]; extern unsigned char RxBuff[BUFFER_SIZE]; extern unsigned char TxBuff[BUFFER_SIZE]; extern unsigned char TxEndFlag;//完成发送标志位 extern unsigned char RxEndFlag;//完成接收标志位 extern unsigned char RxLen;//接收数据长度 /* USER CODE END Private defines */ 7、在“main.c”函数中添加代码如下,定义RxBuff是接收到暂存数组,每次接收到数据后都会把数据存放在这个数组中,因此有很强的实时性,TxBuff是发送暂存数组,每次发送都是这个数组的数据 /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ unsigned int timen;//系统运行绝对时钟,从系统运行开始计时,每1ms自加一次 unsigned short ADC[10]; unsigned char RxBuff[BUFFER_SIZE]; unsigned char TxBuff[BUFFER_SIZE]; unsigned char TxEndFlag;//完成发送标志位 unsigned char RxEndFlag;//完成接收标志位 unsigned char RxLen;//接收数据长度 /* USER CODE END PV */ 8、在“usart.c”文件下添加代码 8.1、找到一下代码 /* Includes ------------------------------------------------------------------*/ #include "usart.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ 添加 “#include "main.h" ” 如下,为了把定义的变量添加进去 /* Includes ------------------------------------------------------------------*/ #include "usart.h" /* USER CODE BEGIN 0 */ #include "main.h" /* USER CODE END 0 */ 8.2.1、在“void MX_USART1_UART_Init(void)”函数的开头找到以下代码 /* USER CODE BEGIN USART1_Init 0 */ /* USER CODE END USART1_Init 0 */ 添加 代码 “unsigned char RxBuff[BUFFER_SIZE]; ” /* USER CODE BEGIN USART1_Init 0 */ unsigned char RxBuff[BUFFER_SIZE]; /* USER CODE END USART1_Init 0 */ 8.2.2、在“void MX_USART1_UART_Init(void)”函数的末尾找到以下代码 /* USER CODE BEGIN USART1_Init 2 */ /* USER CODE END USART1_Init 2 */ 添加 代码 “__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); HAL_UART_Receive_DMA(&huart1,RxBuff,BUFFER_SIZE);” /* USER CODE BEGIN USART1_Init 2 */ __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中断 //DMA接收函数,此句一定要加,不加接收不到第一次传进来的实数据,是空的,且此时接收到的数据长度为缓存器的数据长度 HAL_UART_Receive_DMA(&huart1,RxBuff,BUFFER_SIZE); /* USER CODE END USART1_Init 2 */ 8.3、在“usart.c”文件的最后末尾添加代码,如图 /* USER CODE BEGIN 1 */ void PMJD_UART1_DMA_Send(uint8_t *buf,uint8_t len) { if(TxEndFlag==0)//发送 { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET); for(unsigned short i=0;i<280;i++);//280 if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函数 { Error_Handler(); } } } /* ********************************************************************************************************* * 函 数 名: PMJD_UART1_DMA_Receive * 功能说明: 串口接收功能函数 * 形 参: Data,len * 返 回 值: 无 ********************************************************************************************************* */ void PMJD_UART1_DMA_Receive(void)//串口接收封装uint8_t *Data,uint8_t len { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);//BUFFER_SIZE HAL_UART_Receive_DMA(&huart1,RxBuff,BUFFER_SIZE);//重新打开DMA接收 } void Bsp_break_usartRx(void) { uint32_t tmp_flag = 0; uint32_t temp; tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位 if((tmp_flag != RESET)&(TxEndFlag == 0))//idle标志被置位 { __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位 HAL_UART_DMAStop(&huart1); // temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数 RxLen = BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数 RxEndFlag = 1; // 接受完成标志位置1 } } void Bsp_break_usart_DMA_Tx(void) { TxEndFlag++;//为1时,初始进入中断,开始发送,为2,发送结束 if(TxEndFlag >= 2) { TxEndFlag = 0; PMJD_UART1_DMA_Receive();//接收RS485 } } /* USER CODE END 1 */ 9、打开“usart.h”文件,在文件末尾找到,如下 void MX_USART1_UART_Init(void); /* USER CODE BEGIN Prototypes */ /* USER CODE END Prototypes */ 添加代码 void MX_USART1_UART_Init(void); /* USER CODE BEGIN Prototypes */ void PMJD_UART1_DMA_Send(uint8_t *buf,uint8_t len);//DMA发送数据 void PMJD_UART1_DMA_Receive(void);//DMA重启数据接收 void Bsp_break_usartRx(void);//用于接收中断 void Bsp_break_usart_DMA_Tx(void);//用于发送中断 /* USER CODE END Prototypes */ 10、打开“stm32f1xx_it.c”文件 10.1、添加头文件 “ #include "usart.h" ”如下 /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "stm32f1xx_it.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "usart.h" /* USER CODE END Includes */ 10.2、添加代码“ timen++; ”,“SysTick_Handler”函数是系统时钟,每1ms被调用一次 /** * @brief This function handles System tick timer. */ void SysTick_Handler(void) { /* USER CODE BEGIN SysTick_IRQn 0 */ timen++; /* USER CODE END SysTick_IRQn 0 */ HAL_IncTick(); /* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */ } 10.3、添加代码 “ Bsp_break_usart_DMA_Tx(); ”,如图 void DMA1_Channel4_IRQHandler(void) { /* USER CODE BEGIN DMA1_Channel4_IRQn 0 */ /* USER CODE END DMA1_Channel4_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_usart1_tx); /* USER CODE BEGIN DMA1_Channel4_IRQn 1 */ Bsp_break_usart_DMA_Tx(); /* USER CODE END DMA1_Channel4_IRQn 1 */ } 10.4、添加代码 “ Bsp_break_usartRx(); ”,如图 /** * @brief This function handles USART1 global interrupt. */ void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ Bsp_break_usartRx(); /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ } 11、回到主函数“main.c”中,测试下,可不可以运行 在int main(void)函数中,添加代码 “ unsigned int time; ”如图 /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ unsigned int time;//记录时钟,用于延时等 unsigned char TxBuffTest[BUFFER_SIZE];//用于测试发送数据时的储存器 /* USER CODE END 1 */ 在" while(1) "下添加代码如下,每1s发送一次数据 /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ for(unsigned char i=0;i<10;i++) TxBuff=0x00+i;//数据赋值 TxBuff[10]=0x0D;//这个和下面的共同表示发送结束 TxBuff[11]=0x0A; if((TxEndFlag == 0)&(timen - time >= 1000)) { time = timen; PMJD_UART1_DMA_Send(TxBuff,12);//发送数据 } } /* USER CODE END 3 */ 12、编译,烧入程序,测试接收数据,接收正常,如图,16进制,波特率 9600 13、测试下,接收数据再转发 在 “ while(1) ”的函数中添加代码,如下图 /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ for(unsigned char i=0;i<10;i++) TxBuff=0x00+i;//数据赋值 TxBuff[10]=0x0D;//这个和下面的共同表示发送结束 TxBuff[11]=0x0A; if((TxEndFlag == 0)&(timen - time >= 1000)) { time = timen; PMJD_UART1_DMA_Send(TxBuff,12);//发送数据 } if(RxEndFlag == 1) //接收完成标志 { for(unsigned char i=0;i TxBuffTest=RxBuff; } PMJD_UART1_DMA_Send(TxBuff, RxLen);//发送接收到的数据 memset(RxBuff,0,RxLen);//清除接收到的数据 RxLen = 0;//清除计数 RxEndFlag = 0;//清除接收结束标志位 } } /* USER CODE END 3 */ 由于使用了“memset”函数,需要调用标准函数库 在main.h文件中添加标准库的头文件 “ #include "string.h" ” /* Includes ------------------------------------------------------------------*/ #include "stm32f1xx_hal.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "string.h" /* USER CODE END Includes */ 14、编译、烧入程序,测试收发性能,正常 注:用DMA发送数据,每个消息的数据地址不要用一样的,因为DMA发送的时候,CPU也在工作,DMA数据地址的数据要避免被CPU修改 |
|
|
|
只有小组成员才能发言,加入小组>>
3318 浏览 9 评论
2995 浏览 16 评论
3494 浏览 1 评论
9063 浏览 16 评论
4088 浏览 18 评论
1183浏览 3评论
609浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
601浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2336浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1897浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 01:30 , Processed in 1.200947 second(s), Total 80, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号