USART1:DMA收发
UASRT3:DMA收
问题:
如何USART1做到921600?
需要时钟修改
直接作出MX工程!
编译!
技巧:
放置一个.bat作为del不重要的资源
########上面第一次提交#######
1MX直接创造工程
2int fputc(int ch, FILE *f)//FILE 需要头文件 #include <stdio.h> 放在main.h去吧
{
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1 , 0xffff);
return ch;
}
3此时可以printf了
其实:main.h相当于public.h它是大家伙儿的交集!
增加一个git。bat 目前有问题 CMD不能到GIT
########上面第2次提交#######
增加一个模块进来 比较特殊
–debug模块技巧:只有H没有C #include “…/GKoSonTools/DEBUG/debug.h”
–暂时没有ver技巧 :只有C没有H 需要他上面包含别人的H
模块添加有技巧 不需要IDE修改工程啥的
只需要一句话: #include “…/GKoSonTools/DEBUG/debug.h”
就可以调用啦
########上面第3次提交#######
现在开始利用USART1做测试 DMA_IDLE接收!
第一步 需要数据结构
usart.h
#define RECEIVELEN 1024
typedef struct
{
uint8_t receive_flag:1;
uint16_t rx_len;
uint8_t usartDMA_rxBuf[RECEIVELEN];
}USART_RECEIVETYPE;
extern USART_RECEIVETYPE UsartType1;
extern void UsartReceive_IDLE(UART_HandleTypeDef *huart);
usart.c
USART_RECEIVETYPE UsartType1;
第二部:中断来了处理
void UsartReceive_IDLE(UART_HandleTypeDef *huart)
{
uint32_t temp;
if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
HAL_UART_DMAStop(&huart1);
temp = huart1.hdmarx->Instance->CNDTR;
UsartType1.rx_len = RECEIVELEN - temp;
UsartType1.receive_flag=1;//拉起
HAL_UART_Receive_DMA(&huart1,UsartType1.usartDMA_rxBuf,RECEIVELEN);//再次启动DMA接收啦 所以我DMA不是循环模式而是普通模式
}
}
it:
void USART1_IRQHandler(void)
{
UsartReceive_IDLE(&huart1);
HAL_UART_IRQHandler(&huart1);
}
上面基本可以了
#include “usart.h”
#include <string.h>放在main.h
在任务中测下 来了就发出去
void StartTask02(void const * argument)
{
HAL_UART_Receive_DMA(&huart1, UsartType1.usartDMA_rxBuf, RECEIVELEN);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
/* USER CODE BEGIN StartTask02 /
/ Infinite loop /
PRINT_DEBUG(“WORLD\r\n”);
for(;?
{
if(UsartType1.receive_flag)//如果产生了空闲中断
{
printf("%s\n",UsartType1.usartDMA_rxBuf);//串口打印收到的数据。
memset(&UsartType1,0,sizeof(USART_RECEIVETYPE));
}
osDelay(1);
}
/ USER CODE END StartTask02 */
}
########上面第4次提交#######
上面已经完成了串口的接收 其实在任务里面的代码 最开始是初始化
绑定DMA搬运工的终点站,开始IT,我们进步一步抽象它
第一步:再次抽象数据结构
#define RECEIVELEN 1024
typedef struct
{
UART_HandleTypeDef *huart;
uint8_t rx_flag:1;//1–收到啦中断的时候拉1 0–没收到&处理后请清0
uint8_t tx_flag:1;//1–正忙着sending 0–闲着
uint16_t rx_len;//接收的长度
uint8_t rxBuf[RECEIVELEN];//DMA每次接收的BUF
uint16_t tx_len;//发送的长度 为了照顾BM77 它接收到这个长度的时候停止接收
}GK_USARTIDLE_TYPE ;
extern GK_USARTIDLE_TYPE GKU1;
extern void GK_UsartReceive_IDLE(GK_USARTIDLE_TYPE *myuart);
usart.c
GK_USARTIDLE_TYPE GKU1;
修改中断函数:
void GK_UsartReceive_IDLE(GK_USARTIDLE_TYPE *myuart)
{
uint32_t temp;//if(myuart->huart->Instance==USART1)
if((__HAL_UART_GET_FLAG(myuart->huart,UART_FLAG_IDLE) != RESET))
{
__HAL_UART_CLEAR_IDLEFLAG(myuart->huart);
HAL_UART_DMAStop(myuart->huart);
temp = myuart->huart->hdmarx->Instance->CNDTR;
myuart->rx_len = RECEIVELEN - temp;
myuart->rx_flag=1;//拉起
HAL_UART_Receive_DMA(myuart->huart,myuart->rxBuf,RECEIVELEN);//再次启动DMA接收啦 所以我DMA不是循环模式而是普通模式
}
}
it中
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 /
GK_UsartReceive_IDLE(&GKU1);
/ USER CODE END USART1_IRQn 0 /
HAL_UART_IRQHandler(&huart1);
/ USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
现在我的数据结构扩大了,需要一个绑定GKU1就是USART1的过程函数。
正好在里面完成前面说的任务之前的搬运工/使能中断/优化的动作
uint8_t GK_usart_init(GK_USARTIDLE_TYPE *myuart,uint8_t usartid)
{
switch(usartid)//绑定关系
{
case 1:myuart->huart=huart1;break;
case 3:myuart->huart=huart3;break;
default :return 0;
}
HAL_UART_Receive_DMA(myuart->huart, myuart->rxBuf, RECEIVELEN);//确定DMA搬运收货地址
__HAL_UART_ENABLE_IT(myuart->huart, UART_IT_IDLE);//开启空闲中断
__HAL_UART_CLEAR_IDLEFLAG(myuart->huart);//优化代码:马上清除一次 防止第一次误报
return 1;
}
开始测试:
void StartTask02(void const * argument)
{
printf("%d\r\n",GK_usart_init(&GKU1,1));
/* USER CODE BEGIN StartTask02 /
/ Infinite loop /
PRINT_DEBUG(“WORLD\r\n”);
for(;?
{
if(GKU1.rx_flag)//如果产生了空闲中断
{
printf("%s\n",GKU1.rxBuf);//串口打印收到的数据。
memset(GKU1.rxBuf,0,RECEIVELEN);//用完就毁灭清为0
GKU1.rx_flag=0;
}
osDelay(1);
}
/ USER CODE END StartTask02 */
}
########上面第5次提交#######
上面测试很不错!!
现在进一步模块化 任务是做一个USART的收发函数。
uint8_t GK_usart_TXRX(GK_USARTIDLE_TYPE *myuart, uint8_t *TX ,uint16_t TXlen ,uint8_t *RX,uint16_t *RXlen)
{
uint8_t Cnt = 10;
HAL_UART_Transmit(myuart->huart, TX, TXlen, 0xFFFF);
while(Cnt--)//尝试次数 10次 这里面其实需要喂狗 每次这样的情形都有喂狗
{
if(myuart->rx_flag)//在中断拉起1
{
memcpy(RX,myuart->rxBuf,myuart->rx_len);
*RXlen=myuart->rx_len;
memset(&myuart->rxBuf,0,RECEIVELEN);//用完就毁灭清为0
myuart->rx_flag=0;
return 1;
}
HAL_Delay(10);
}
return 0;
}
等待测试