最近做了两个单片机项目,新唐的029和mini58ZDE的MCU,都是cortex-M0,一个厂家所以API基本一致,大致了解了串口中断及定时器功能以及ADC采样相关的编程内容。
4G项目即mini58zde,主要是从GPS中读数据然后从另外一个串口转发出去
GPS模块 ------ 串口1接收 ----数据处理组包 -----串口0发送------上位机
GPS模块是不断地有数据来,数据格式为
$GNRMC,014053.00,A,3205.65222,N,11853.26056,E,0.038,,030817,,,D,V*18
$GNGGA,014053.00,3205.65222,N,11853.26056,E,2,14,0.81,52.6,M,3.1,M,,*41
$GNGSA,A,3,01,09,11,16,08,30,28,,,,,,1.36,0.81,1.09,1*0A
$GNGSA,A,3,03,07,08,01,02,04,13,,,,,,1.36,0.81,1.09,4*08
$GPGSV,4,1,16,01,47,176,41,04,12,058,,07,66,274,,08,55,026,30,0*63
$GPGSV,4,2,16,09,10,223,30,10,03,059,28,11,72,198,46,16,16,098,45,0*6F
$GPGSV,4,3,16,17,02,245,23,22,05,152,18,23,02,197,,27,23,049,18,0*65
$GPGSV,4,4,16,28,17,303,37,30,36,311,29,42,43,137,42,50,43,137,42,0*67
$BDGSV,3,1,10,01,48,143,43,02,37,232,39,03,53,196,43,04,33,121,35,0*78
$BDGSV,3,2,10,05,16,252,,07,76,112,44,08,69,219,44,10,74,327,,0*7E
$BDGSV,3,3,10,13,43,220,42,17,50,110,,0*75
$GNTXT,1,1,01,ANTENNA OPEN*3B
主要处理的数据是GNRMC和GNGGA,用了状态机的方法判断前面GMRMC/GNGGA之后直接判断是否是 ‘*’,因为逐个判断状态太多,很复杂而且容易出错,读取到 * 之后,再读校验位,校验成功的话,将数据拷贝到 处理缓冲区置标志位,在主程序中检测标志位,然后处理数据,更新数据
串口0 既要接受命令也要返回数据,串口0的数据接受为固定长度的,在这里也使用了状态机,提取出命令码之后,将命令码写到命令队列中,这样就能及时响应下一个命令,不用死等,数据接收与数据处理独立运行,不会造成高耦合的现象
串口0 接收数据提取命令码---------压入命令队列 POP(中断中实现)
串口1 接受提取有效数据-------------更新GPS数据结构体(中断中实现)
主程序 读取命令队列----------------出列PUSH ,根根不同的命令将GPS数据组包通过串口0发出去。
主程序中使能看门狗,使用定时器喂狗。
开发中遇到的一些问题:
1.设计思路有问题,没理清流程,一开始以为接受到命令码马上处理,造成串口0一直要等待
2.看门狗操作寄存器是写保护,要先解保护才能操作,厂家给的示例不对,造成看门狗使能失败,喂狗失败。
3.状态机使用出错,状态太多,两条命令混合处理,造成代码混乱,很难理清。
4.铁塔协议花了很久才明白是怎么一回事,要多看代码才行。
5.内部时钟的配置,要根据实际情况来,没有外部时钟就不能用,
029电源控制模块:
电源充放电管理的一个小模块,几个条件限制充放电
低于5度不充电,电压低于6.1V或者放电时间到了20MIN不放电
使用了GPIO的中断 确定什么时候开始放电,电源关闭,下降沿触发,电池开始放电。重新上电,上升沿,电池可以开始充电。代码很简单主要是ADC采样还有定时器中断的问题,
电压和温度都是通过ADC采样转换实现的,使用内部温度,一个管脚配置成温度传感器,然后进行ADC采样,电压基准源采用的是3.3V,这个项目没有串口,打印会造成很多异常,debug下正常但正常跑起来却有问题,所以调试时尽量少用或者不用printf,整个程序很简单,就是控制GPIO口
开发中遇到的一些问题:
1.添加printf造成程序异常,定时器异常
2.一上电就进行ADC采样不对,电压还没有升上来,采样的值很小,等待10ms之后采样值就对了
3.float 数据计算及比较要注意
void UART1_RT_STATE(uint8_t u8InChar)
{
uint8_t TempBuf[3]= {0};
uint8_t CheckSum = 0;
switch(x_RecvState)
{
case WaitingForHeads:
if(u8InChar == '$')
{
UART1_Rx_buff[0] = u8InChar;
x_RecvState = WaitingForG;
}
else
{
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
break;
case WaitingForG:
if(u8InChar == 'G')
{
UART1_Rx_buff[1] = u8InChar;
x_RecvState = WaitingForN;
}
else
{
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
break;
case WaitingForN:
if(u8InChar == 'N')
{
UART1_Rx_buff[2] = u8InChar;
x_RecvState = WaitingForG_R;
}
else
{
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
break;
case WaitingForG_R:
if(u8InChar == 'G')
{
UART1_Rx_buff[3] = u8InChar;
x_RecvState = WaitingForG_2;
}
else if(u8InChar == 'R')
{
UART1_Rx_buff[3] = u8InChar;
x_RecvState = WaitingForM;
}
else
{
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
break;
case WaitingForG_2:
if(u8InChar == 'G')
{
UART1_Rx_buff[4] = u8InChar;
x_RecvState = WaitingForA;
}
else
{
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
break;
case WaitingForM:
if(u8InChar == 'M')
{
UART1_Rx_buff[4] = u8InChar;
x_RecvState = WaitingForC;
}
else
{
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
break;
case WaitingForC:
if(u8InChar == 'C')
{
UART1_Rx_buff[5] = u8InChar;
x_RecvState = WaitingForRs;
rcv_count = 6;
gps_flag = RMC;
}
else
{
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
break;
case WaitingForA:
if(u8InChar == 'A')
{
UART1_Rx_buff[5] = u8InChar;
x_RecvState = WaitingForGs;
rcv_count = 6;
gps_flag = GGA;
}
else
{
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
break;
case WaitingForRs:
if(u8InChar != '*')
{
UART1_Rx_buff[rcv_count++] = u8InChar;
if(rcv_count > 65)
{
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
else
x_RecvState = WaitingForRs;
}
else
{
if(rcv_count != 65)
{
if(rcv_count == 37)
{
gps_flag = NOUSE;
DATA_ANY = 1;
}
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
else
{
UART1_Rx_buff[rcv_count++] = u8InChar;
x_RecvState = WaitingForChsum_1;
}
}
break;
case WaitingForGs:
if(u8InChar != '*')
{
UART1_Rx_buff[rcv_count++] = u8InChar;
if(rcv_count > 68)
{
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
else
x_RecvState = WaitingForGs;
}
else
{
if(rcv_count != 68)
{
if(rcv_count == 36)
{
gps_flag = NOUSE;
DATA_ANY = 1;
}
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
}
else
{
UART1_Rx_buff[rcv_count++] = u8InChar;
x_RecvState = WaitingForChsum_1;
}
}
break;
case WaitingForChsum_1:
// printf("gf = %d\n",gps_flag);
UART1_Rx_buff[rcv_count++] = u8InChar;
x_RecvState = WaitingForChsum_2;
break;
case WaitingForChsum_2:
TempBuf[0]= UART1_Rx_buff[rcv_count-1];
TempBuf[1]=u8InChar;
TempBuf[2]=0;
CheckSum=strtoul(TempBuf,NULL,16);
UART1_Rx_buff[rcv_count++] = u8InChar;
Checkret = GpsChecksum(CheckSum);
x_RecvState = WaitingForEnd_1;
break;
case WaitingForEnd_1:
if(u8InChar == 0xD)
{
UART1_Rx_buff[rcv_count++] = u8InChar;
x_RecvState = WaitingForHeads;
if(Checkret)
{
#if 0
if(gps_flag == GGA)
P13 = 1;
if(gps_flag == RMC)
P13 = 0;
#endif
memcpy(UART1_Pr_buff,UART1_Rx_buff,rcv_count);
Checkret = 0;
DATA_ANY = 1;
}
}
x_RecvState = WaitingForHeads;
rcv_count = 0;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
break;
default:
rcv_count = 0;
x_RecvState = WaitingForHeads;
memset(UART1_Rx_buff,0,sizeof(UART1_Rx_buff));
break;
}
}