梅花香自123
发表于 2022-6-29 21:25
并在keil的设置添加文件路径:
梅花香自123
发表于 2022-6-29 21:25
将库文件下的.c文件添加到工程中
梅花香自123
发表于 2022-6-29 21:26
五、MM32配置代码
GPS在传输数据的时候是串口接收的,因此大量的数据在串口传输时候,如果使用mcu来进行循环处理,这将大大降低CPU的效率
因此这里选择串口dma,硬件数据传输,但是网上关于灵动单片机的dma配置资源比较少,这里我将我的代码配置出来。
梅花香自123
发表于 2022-6-29 21:26
5-1 GPS接口初始化
主要包括串口初始化和串口dma配置
梅花香自123
发表于 2022-6-29 21:27
///**
//* @briefGPS_Config gps 初始化
//* @param无
//* @retval 无
//*/
void GPS_Config(void)
{
GPS_USART_Config();
GPS_DMA_Config();
}
梅花香自123
发表于 2022-6-29 21:28
GPS_USART_Config函数
主要是对mm32 与定位模块连接的 USART 串口外设作了基本的初始化,除了要注意把波特率配置为 9600,其它跟普通串口配置无异。
梅花香自123
发表于 2022-6-29 21:28
/*
* 函数名:GPS_USART_Config
* 描述:USART GPIO 配置,工作模式配置
* 输入:无
* 输出: 无
* 调用:外部调用
*/
static void GPS_USART_Config(void)
{
uart_init(GPS_UART, GPS_USART_BAUDRATE, GPS_USART_RX, GPS_USART_TX);
uart_rx_irq(GPS_UART, 1);
}
梅花香自123
发表于 2022-6-29 21:43
GPS_DMA_Config 函数
MM32DMA相关的宏定义:这部分可以查阅芯片手册得到:
//DMA
#define GPS_USART_DMA_STREAM DMA2_Channel3
#define GPS_DMA_IRQn DMA2_Channel3_IRQn //GPS中断源
#define GPS_USART_DMA_CLK RCC_AHBENR_DMA2
#define GPS_USART_DMA_CHANNEL DMA_Channel_3
/* 外设标志 */
#define GPS_DMA_IT_HT DMA2_IT_HT3 //DMA_IT_HTIF5
#define GPS_DMA_IT_TC DMA2_IT_TC3 //DMA_IT_TCIF5
#define UART_DMAReq_Rx ((uint16_t)0x0040)
/* 中断函数 */
#define GPS_DMA_IRQHANDLER DMA2_Channel3_IRQHandler //GPS使用的DMA中断服务函数
梅花香自123
发表于 2022-6-29 22:39
串口接收缓冲区地址宏定义
梅花香自123
发表于 2022-6-29 22:49
#define GPS_DATA_ADDR (u32)&UART4->RDR //GPS_DR_Base //GPS使用的串口的数据寄存器地址
#define GPS_RBUFF_SIZE 512 //串口接收缓冲区大小
#define HALF_GPS_RBUFF_SIZE (GPS_RBUFF_SIZE/2) //串口接收缓冲区一半
梅花香自123
发表于 2022-6-29 22:50
重点在串口 DMA 的配置,代码如下
梅花香自123
发表于 2022-6-29 22:52
/**
* @briefGPS_Interrupt_Config 配置GPS使用的DMA中断
* @paramNone.
* @retval None.
*/
static void GPS_Interrupt_Config(void)
{
exNVIC_Init_TypeDefNVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStruct.NVIC_IRQChannel = GPS_DMA_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
exNVIC_Init(&NVIC_InitStruct);
}
/**
* @briefGPS_DMA_Config gps dma接收配置
* @param无
* @retval 无
*/
static void GPS_DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
/*开启DMA时钟*/
RCC_AHBPeriphClockCmd(GPS_USART_DMA_CLK, ENABLE);
/* 复位初始化DMA数据流 */
DMA_DeInit(GPS_USART_DMA_STREAM);
DMA_StructInit(&DMA_InitStructure);
/*设置DMA源:串口数据寄存器地址*/
DMA_InitStructure.DMA_PeripheralBaseAddr = GPS_DATA_ADDR;
/*内存地址(要传输的变量的指针)*/
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)gps_rbuff;
/*方向:从外设到内存*/
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
/*传输大小DMA_BufferSize=SENDBUFF_SIZE*/
DMA_InitStructure.DMA_BufferSize = GPS_RBUFF_SIZE;
/*外设地址不增*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
/*内存地址自增*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/*外设数据单位*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
/*内存数据单位 8bit*/
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
/*DMA模式:不断循环*/
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/*优先级:中*/
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
//M2M mode is disabled
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 非内存到内存模式
DMA_InitStructure.DMA_Auto_reload = DMA_Auto_Reload_Enable;
/*配置DMA2的数据流3*/
DMA_Init(GPS_USART_DMA_STREAM, &DMA_InitStructure);
// Enable UARTy_DMA1_Channel Transfer complete interrupt
DMA_ITConfig(GPS_USART_DMA_STREAM, DMA_IT_HT|DMA_IT_TC, ENABLE);
/* 配置串口 向 DMA发出请求 */
UART_DMACmd(UART4, UART_DMAReq_EN, ENABLE);
/*使能DMA*/
DMA_Cmd(GPS_USART_DMA_STREAM, ENABLE);
/*配置中断优先级*/
GPS_Interrupt_Config();
}
梅花香自123
发表于 2022-6-29 22:55
GPS_DMA_Config 函数主要工作如下: 设置了外设地址为 USART 的数据寄存器,并把数据传输方向设置为从USART 数据寄存器传输到内存变量 gps_rbuff 中,该缓冲区数组大小为 512 字节。
DMA2_Channel3_IRQHandler中断函数
梅花香自123
发表于 2022-6-29 22:57
最关键的位置它设置了 DMA 半传输结束中断及全传输结束中断,
//配置 DMA 发送完成后产生中断
DMA_ITConfig(GPS_USART_DMA_STREAM,DMA_IT_HT|DMA_IT_TC,ENABLE);
梅花香自123
发表于 2022-6-29 23:02
所以它实际把缓冲区分为成了大小相等的 A/B 两部分,每次 DMA 接收了半个缓冲区大小的数据时(本程序为256 字节),就会引起中断得益于这个机制。
梅花香自123
发表于 2022-6-29 23:02
可以设计程序当 DMA 使用缓冲区 A 存储数据时,控制 CPU 使用 B中的数据进行 GPS 解码,当 DMA 使用 B 存储时,控制 CPU 使用 A 进行解码,只要缓冲区的大小设置合适,即可避免前面说到的数据丢失问题,这种处理方式也称“乒乓缓冲”,得名于它像打乒乓球一样,你来我往。
梅花香自123
发表于 2022-6-29 23:03
当 DMA 的 半 传 输 中 断 或 全 传 输 中 断 产 生 时 , 进 入 的 中 断 服 务 函 数 调 用 了DMA2_Channel3_IRQHandler函数
梅花香自123
发表于 2022-6-29 23:04
void DMA2_Channel3_IRQHandler(void)
{
if(DMA_GetITStatus(GPS_DMA_IT_HT) ) /* DMA 半传输完成 */
{
GPS_HalfTransferEnd = 1; //设置半传输完成标志位
DMA_ClearITPendingBit (GPS_DMA_IT_HT);
}
else if(DMA_GetITStatus(GPS_DMA_IT_TC)) /* DMA 传输完成 */
{
GPS_TransferEnd = 1; //设置传输完成标志位
DMA_ClearITPendingBit(GPS_DMA_IT_TC);
}
}
梅花香自123
发表于 2022-6-29 23:04
在 这 个 函 数 处 理 中 , 主 要 是 在 半 传 输 和 全 传 输 结 束 引 起 中 断 时 , 对GPS_HalfTransferEnd 和 GPS_TransferEnd 标志位进行标记, 在解码流程中根据这两个标志使用不同的缓冲区进行处理。
梅花香自123
发表于 2022-6-29 23:05
5-2 解码测试函数nmea_decode_test()
解码函数主要是调用函数库中的函数,并加标志位进行处理。