本帖最后由 cepoly 于 2014-7-3 16:19 编辑
大体实现:GPS连接STM32F0单片机串口,利用中断接收,但不知道串口接收数据长度,GPS数据长度受卫星信号影响,我一直在找硬件寄存器标志,即数据接收结束后,这个寄存器标志响应,然后我就可以读个寄存器来判定数据接收完毕!
1.GPS数据长度不确定(最大可达1024个byte),如:
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,00*79
$GPGLL,,,,,,V,N*64
我的程序如下:
void USBD_USR_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHBPeriphClockCmd (RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
/*
* USART1_TX -> PA9 , USART1_RX ->;PA10
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_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(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1, ENABLE);
}
#include "usbd_cdc_core.h"
#include "stm32f0xx_tim.h"
#include "usbd_usr.h"
#include "string.h"
#define BYTE_SIZE 1024
#define SEND_TO_USB 1
#define SEND_TO_USB_END 0
#define CLR_REV_BYTE 0
#define CLR_REV_TIME 0
#define UART_REV_TIME 1
USB_CORE_HANDLE USB_Device_dev ;
typedef struct
{
uint32_t bitrate;
uint8_t format;
uint8_t paritytype;
uint8_t datatype;
}LINE_CODING;
LINE_CODING serial ={9600, 0x00, 0x00, 0x08};
static uint8_t RevChar[BYTE_SIZE];
static volatile uint16_t RevSize,SendByte;;
static volatile uint8_t rev_end;
static volatile uint8_t rev_flag;
static volatile uint8_t time_add;
static uint8_t Author[26] = "**** poly 2014.06.21 *****";
static uint8_t test[5] = {5,6,7,8,9};
void Delay_us(__IO uint32_t nCount);
void Delay_ms(__IO uint32_t nCount);
void NVIC_Config(void);
void TIM2_Config(void);
void USART1_TX_DataN (uint8_t *pData,uint16_t TX_NumByte);
int main(void)
{
RevSize = 0;
rev_end = 0;
rev_flag = 0;
NVIC_Config();
TIM2_Config();
memset(RevChar, '\0', BYTE_SIZE);
USBD_Init(&USB_Device_dev, &USR_desc, &USBD_CDC_cb, &USBD_USR_Init);
//USART1_TX_DataN (Author, 26);
while (1)
{
if((SendByte > 0) && (rev_end == SEND_TO_USB))
{
//USART1_TX_DataN (RevChar, SendByte);
DCD_EP_Tx (&USB_Device_dev, CDC_IN_EP, RevChar, SendByte);
memset(RevChar, '\0', BYTE_SIZE);
rev_end = SEND_TO_USB_END;
rev_flag = CLR_REV_TIME;
}else{
if(time_add > 5)
{
//DCD_EP_Tx (&USB_Device_dev, CDC_CMD_EP, "a", 1);
//中断传输,CDC协议说是传输串口状态,论坛上坛友说用户不能用这个中断传输,目前我直接写字节传 //输,主机HOST端也可以接收到
time_add = 0;
}
}
}
}
/******************************************************************************
* Function Name : USART1_IRQHandler
* Description : USART1
******************************************************************************/
void USART1_IRQHandler(void)
{
if(rev_flag == CLR_REV_TIME)
{
TIM_Cmd(TIM2,ENABLE);
rev_flag = UART_REV_TIME;
}
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
if (serial.datatype == 7)
{
RevChar[RevSize] = USART_ReceiveData(USART1) & 0x7F;
}
else if (serial.datatype == 8)
{
RevChar[RevSize] = USART_ReceiveData(USART1);
}
}
RevSize++;
// USART_SendData(USART1,RevChar[RevSize]);
}
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);
}
TIM_Cmd(TIM2,DISABLE);
rev_end = SEND_TO_USB;
SendByte = RevSize;
RevSize = CLR_REV_BYTE;
time_add ++;
}
void Delay(__IO uint32_t nCount)
{
/* Decrement nCount value */
while (nCount != 0)
{
nCount--;
}
}
void Delay_us(__IO uint32_t nCount)
{
/* 10uS=>10.8uS,100uS=>104uS*/
while (nCount != 0)
{
nCount--;
Delay(10);
}
}
void Delay_ms(__IO uint32_t nCount)
{
/* 10uS=>10.8uS,100uS=>104uS*/
while (nCount != 0)
{
nCount--;
Delay(11000);
}
}
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM2_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Period = 65536;
TIM_TimeBaseStructure.TIM_Prescaler = 550;//n * 1.5ms
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM2,DISABLE);
}
void USART1_TX_DataN(uint8_t *pData,uint16_t TX_NumByte)
{
uint16_t i;
for(i=0;i<TX_NumByte;i++)
{
USART_SendData(USART1,*pData++);
// #if(USART1_BaudRate==115200)
// Delay_us(90);
// #if(USART1_BaudRate==19200)
// Delay_us(500);
// #if(USART1_BaudRate==9600)
// Delay_us(1000);
Delay_us(1000);
USART_ClearFlag(USART1,USART_FLAG_TXE);
}
}
终于解决了数据完整帧接收,以上代码分享交流下,看看各位有没有更好的办法,继续优化
目前的办法是:中断接收GPS数据,后台开一个定时器来判断数据完整帧的结束
TIM_TimeBaseStructure.TIM_Prescaler = 150;这里会影响到数据完整帧的判断,如果开的过小,比如2ms- 100ms检查一次
我这边每一帧数据中(286 byte以上),总是会丢掉2个字节,而且丢掉的字节都相同位置的
比如完整帧如下:
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,00*79
$GPGLL,,,,,,V,N*64
接收到的时候是:
$RMC,,V,,,,,,,,,,N*53 丢掉两个字节
$GPVTG,,,,,,,,,N*30
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,00*79
$GPGLL,,,,,,V,N*64
实在找不到具体是什么原因,只能更改定时器检测时间 TIM_TimeBaseStructure.TIM_Prescaler = 150;
大概1500ms检测一次就不会丢字节,已知GPS是每秒发送一帧数据
|
|