最近做了两个单片机项目,新唐的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 ",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; } }