查看: 16510
回复: 23
参赛作品《基于STM8S/STM32F0定位跟踪器》

主题

回复
发表于2017-06-01 12:56:07 | 显示全部楼层
1# 电梯直达

【报名阶段需要填写的内容】


1. 参赛者姓名(必填项):郭同学


2. 单位或学校名称(必填项):深圳市易联通信技术有限公司


3. 当前职务或职称(必填项):技术员


4. 参赛作品的名字(必填项):基于STM32F042/STM8S定位跟踪器


5. 简要陈述您的idea和作品(必填项):成本低、定位快、超省电、体积小


6. 拟用到的立创商城在售物料(必填项):STM8S003F3P6、 MMSZ4689 5.1V CU、XL1509-ADJE1 / SOP-8_150mi、SS24 / SMB(DO-214AA)


7. 拟用到的非立创商城物料或其它补充(必填项):SIM800C模块、泰斗GPS模块


【作品正式发表(报名成功后进入设计阶段)需要填写的内容】


产品完全资料包(参赛作品-基于STM8SSTM32F0定位跟踪器-资料包.zip )


一、作品简介

1、作品背景简介

     如今的社会对位置服务已经有了较为普遍的认识。这得益于两方面:一是智能手机的普及和各种基于位置服务的APP(例如:美团)的普及。二是各种带了位置服务的物联网产品(以下简称GNSS终端)的普及。GNSS终端主要通过定位卫星或手机通讯基站来计算GNSS终端当前所处的位置。在我国的GNSS终端通常使用的是美国的GPS和本土的北斗卫星来获取当前位置。GNSS终端在物流跟踪、车辆防盗等方便应用比较广泛。本文将介绍一款基于STM32F042的低成本、高可靠性、易嵌入的GNSS终端的原理及制作方法。

GNSS终端主要包括:MCU电路、电源模块、定位模块(可选用北斗或双模卫星定位模块)模块、数据通信模块、扩展模块。

MCU电路:基于STM32F042为处理器的数据处理、功能实现电路。

电源模块:本终端使用4.2V锂电池为系统供应电能,使用TP4054为锂电池充电。

定位模块:选用泰斗公司的北斗+GPS双模定位模块。其具有定位快、少漂移、轨迹平滑等特点。由于该模块的封装为常用封装因而可直接更换其它厂家的相同封装的定位模块(例如:GTOP、中科威等)。

数据通信模块:选用希姆通公司的SIM800C为本终端的通信模块。其体积小、通信稳定、支持GSM四频,另外其价格也比较实惠。

       扩展模块:扩展模块主要包含由继电器构成的防盗电路。用户可以用过该模块来实现远程控制、远程安防等功能。

2、作品亮点

与市面上现有的GNSS终端相比,本方案具有以下创新和特点:

①       本设计所使用的器件较少,因而其成本很低。

②       本设计所选用的MCU为国际品牌STM32F042,所以其具有高可靠性和系统运行的稳定性以及低功耗的特性。

③       本方案使用锂电池供电因而可以放置任何需要跟踪的物品中,如果需要长时间跟踪只需要外挂一个大容量的充电宝即可。

④       本设计的大部分阻容器件都使用0402封装,使得PCBA体积小,因此可以很方便的嵌入到其它产品中为其实现位置服务。

⑤       本设计使用了独特的AGPS算法可以实现GPS快速定位的功能。


二、系统构架图


系统解说:本方案基于STM32F042实现位置服务,MCU通过串口与通信模块、GPS模块通信。


三、硬件部分的描述

原理图(原理图.pdf )分为多个部分,下面逐个介绍:

第一部分: MCU电路

  点击查看大图

备注说明:上图中,STM32F042G6的封装是QFN-28_4x4x05P,能节省PCB板的空间使用,自动复位电路是MCU电路的技巧性电路。当烧录程序时BOOT0被拉高,电容C4开始充电,三极管Y1CE极导通,MCU复位引脚被拉低。当C4充满电后三极管Y1CE极截止,MCU复位引脚拉高;此过程产生了一个复位脉冲使得MCU复位后进入BOOT模式,这极大的方便了程序烧录也简化了程序烧录相关的电路。

 

第二部分:系统供电部分

点击查看大图

备注说明:本系统使用锂电池供电,由XC6802(或TP4054)为其充电。外部5V电源通过保险丝后再经过SS34二极管到达充电IC的输入端。3.3V电路由MIC5255(本系统选用的是MIC5205-3.3BM5LDO电路构成。GPSGSM的电源都使用MOSMEM2301XG进行控制。

 

第三部分:定位模块

点击查看大图

备注说明:如上图所示,GNSS电路使用的是市面上较为流行的1612邮票封装,可兼容多家GNSS模块。使用的是有源陶瓷天线。GNSS电源使用了一组电容进行滤波以确保GNSS模块内部不受到电源上的杂波干扰。

 

第四部分:数据通信模块

点击查看大图

备注说明:如上图所示,数据通信模块电路使用的是SIM800C模块,为了降低产品体积其电源引脚上的电容采用647uF的并联构成。

 

第五部分:扩展模块

因扩展模块涉及客户保密信息并且其对GPS跟踪器的原理介绍与设计并没有影响。因此省略了这部分电路的介绍,望理解。


附帖好的PCB实物图:

正面

 

反面

 

1毛硬币合拍照

 

天线接入照片

 

 

GNSS信号分析照片

 点击查看大图

 点击查看大图

 点击查看大图

 点击查看大图


四、材料清单(BOM列表)


以下是这个电子制作的BOM列表(方案验证板的BOM清单.zip) ,部分器件采购来自立创商城http://www.szlcsc.com,PCB板的制造在深圳嘉立创完成并在嘉立创贴片。

 点击查看大图



五、软件部分的描述(选填)


软件部分,这里主要展现GNSS模块、通信模块的核心代码和流程图。本系统中,关键部分的代码是GNSS模块数据解析及AGPS工作流程、通信模块的初始化步骤。

AGPS流程图

<!--[if !vml]--><!--[endif]-->

AGPS源码

void Gps_AGpsHandle(void)
{
	static u8 ErrG;
	
	if((User.Sleep==1) || (User.SleepRdy==1))
		return;

	if(Gps.Manage.fAssitReq)
	{
		if((User.GpsFixed==0) && (DEV_BUF[0]=='S') && (User.TestOpen==0))
		{
			if(AGps.DataOK==0 || ((T5ms-AGps.WrPoint)>=T_90MIN))
			{
				AGpsPos=0;
				pub_memset_gps(AGpsBuf,0,sizeof(AGpsBuf));
				if( Gps_SendMessageToMain(GPS_ASSIT_REQ,0,NULL)==GD_ERR)
						Gps_SendMessageToMain(GPS_ASSIT_REQ,0,NULL);
			}
			else
			{
				Gps_SendAssitData();
			}
		}
		Gps.Manage.fAssitReq=0;
	}
	
	OSFlagAccept(pFlagsEvent,(OS_FLAGS)FLAGS_SET_GPS,OS_FLAG_WAIT_SET_ALL|OS_FLAG_CONSUME,&ErrG);
	if(ErrG == OS_ERR_NONE)
	{
		if(User.GpsMsgType==GPS_MSG_SET_APGS)
		{
			if(User.GpsFixed==0)
			{
				Gps_SendAssitData();
			}
		}
		else if(User.GpsMsgType==GPS_MSG_SET_OPEN_DEBUG)
		{
			Gps_ConfigALL();
			SubUser.GpsDebugCnt=0;
			SubUser.GpsDebugOpen=1;
		}
		else if(User.GpsMsgType==GPS_MSG_SET_CLOSE_DEBUG)
		{
			Gps_Config();
			SubUser.GpsDebugCnt=0;
			SubUser.GpsDebugOpen=0;
		}
	}
}


GNSS串口数据解析出数据帧流程图

 

 GNSS串口数据解析出数据帧源码

s8 Gps_DataDecode(void)
{
		static u8  RevSt=0;
		static u8  FlagFind=0;
		static s16 i=0;
		static u16 SBuf[3];
		static double SpeedCal=0;
	
#if CFG_TEST_TASK_TIME
		static u32 OldCycPoint=0;
		static u32 OldCycFirst=1;
	
		if((T5ms-OldCycPoint)>SubUser.Task_GpsMax)
			SubUser.Task_GpsMax=(T5ms-OldCycPoint);
		OldCycPoint=T5ms;	
	
		if(OldCycFirst)
		{
			SubUser.Task_GpsMax=0;
			OldCycFirst=0;
		}
#endif
	
	TempGLen = Bsp_UartRead_Gps(UART_INDEX_GPS, TempGBuf, sizeof(TempGBuf));
	if(TempGLen<=0) 
		return GD_ERR;	

	
	for(i=0;i<TempGLen;i++)
	{
		if(Gps_CheckData(TempGBuf[i])==GD_OK)			//找到一帧数据	
		{
			     if(pub_StringCompare(GpsInBuf,"$GPRMC")>=6)	FlagFind = 1;
			else if(pub_StringCompare(GpsInBuf,"$GPGGA")>=6)	FlagFind = 2;
			else if(pub_StringCompare(GpsInBuf,"$GPGSA")>=6)	FlagFind = 4;

#if 1		
			else if(pub_StringCompare(GpsInBuf,"$GNRMC")>=6) 	FlagFind = 1;
			else if(pub_StringCompare(GpsInBuf,"$GNGGA")>=6) 	FlagFind = 2;
			else if(pub_StringCompare(GpsInBuf,"$GNGSA")>=6)	FlagFind = 4;
			else if(pub_StringCompare(GpsInBuf,"$BDRMC")>=6) 	FlagFind = 1;
			else if(pub_StringCompare(GpsInBuf,"$BDGGA")>=6) 	FlagFind = 2;
			else if(pub_StringCompare(GpsInBuf,"$BDGSA")>=6)	FlagFind = 4;			
#endif
			else 												FlagFind = 0;

			if(FlagFind)
			{
				if(FlagFind==1)
				{
					if(Gps_RMC_Decode(GpsInBuf,&Gps.GpsData.RMC,GPS_IN_BUF_SIZE)==GD_OK)
						RevSt |= 0x01;
				}
				else if(FlagFind==2)
				{
					if(Gps_GGA_Decode(GpsInBuf,&Gps.GpsData.GGA,GPS_IN_BUF_SIZE)==GD_OK)
						RevSt |= 0x02;
				}
				else if(FlagFind==4)
				{
					if(Gps_GSA_Decode(GpsInBuf,&Gps.GpsData.GSA,GPS_IN_BUF_SIZE)==GD_OK)
						RevSt |= 0x04;
				}

				Gps.Check.tFault = T5ms;
				Gps.Check.fMoudleFault = 0;
				if(User.GpsFault.Error)
				{
					User.GpsFault.Error=0;
					User.GpsFault.Rep=0;
					User.GpsFault.Saved=0;
				}

				if((RevSt&0x07)==0x07)
				{
					RevSt=0;
					//RMC计算部分放大了1000
					SpeedCal=Gps.GpsData.RMC.Speed;	
					SpeedCal=(SpeedCal*1.852)/100.0;
					Gps.GpsData.SpeedKmH = (u16)SpeedCal;	//放大10倍
					
					if(SpeedCal<36 || SpeedCal>2500)
					{
								pub_memset_gps((u8*)SBuf,0,sizeof(SBuf));
								Gps.GpsData.SpeedMS=0;
								Gps.GpsData.SpeedKmH=0;
					}
					else
					{
								SBuf[0]=SBuf[1];
								SBuf[1]=SBuf[2];
								SBuf[2]=(u16)(SpeedCal/3.6);
								Gps.GpsData.SpeedMS=(SBuf[0]+SBuf[1]+SBuf[2])/3;
					}
					Gps_DataUpdate();
					Gps_AccCheck();
					Gps_ShpTnCheck();
				}
			}
			FlagFind=0;			
			pub_memset_gps(GpsInBuf,0,GPS_IN_BUF_SIZE);
		}
	}
	return GD_OK;
}


RMC数据帧解析出数据字段流程图

<!--[if !vml]-->点击查看大图<!--[endif]-->

RMC数据帧解析出数据字段源码

s8 Gps_RMC_Decode(u8 *pIn,GPRMC *pRMC,u16 len)
{
	s16 offset=0,end=0;
	
	//$GPRMC,010101.130,A,3606.6834,N,12021.7778,E, 0.0,238.3,010807,,,A*6C\r\n
	//$GPRMC,021510.00,  A,2231.83115, N,  11355.27851,  E,  0.077,  , 290312,,,A*7A  	
	end = pub_GetCharPositionGps(pIn,'\n',len);
	if(end==GD_ERR)
		return GD_ERR;
	
	//TIME
	if(pub_FieldCheckGps(&offset,pIn,end,GPS_GPRMC_FIELD_TIME)==GD_ERR)
		return GD_ERR;
	if(*(pIn+offset)==',')	
	{
		pRMC->Time.Hour=0;
		pRMC->Time.Min=0;
		pRMC->Time.Sec=0;
	}
	else
	{			
		pRMC->Time.Hour =0;
		pRMC->Time.Hour =pub_DecAscToU32(pIn+offset,2,1);
		offset+=2;
		
		pRMC->Time.Min=0;
		pRMC->Time.Min=pub_DecAscToU32(pIn+offset,2,1);
		offset+=2;
		
		pRMC->Time.Sec =0;
		pRMC->Time.Sec =pub_DecAscToU32(pIn+offset,2,1);
		offset+=2;
	}
	
	//STATUS		
	if(pub_FieldCheckGps(&offset,pIn,end,GPS_GPRMC_FIELD_STATUS)==GD_ERR)
		return GD_ERR;		
	if(pIn[offset] == 'A')	pRMC->Fixed = 'A';
	else					pRMC->Fixed = 'V';
	
	//Latitude
	if(pub_FieldCheckGps(&offset,pIn,end,GPS_GPRMC_FIELD_LATITUDE)==GD_ERR)
		return GD_ERR;
	if(*(pIn+offset)==',') 	pRMC->Latitude = 0;
	else
	{
		//2230.282411
		u32 temp1=0,temp2=0;
		double IntPart=0,DecPart=0;
		u8 BitNum=0;
		
		temp1=pub_DecAscToU32(pIn+offset,4,1);
		offset+=4;		
		offset+= pub_GetCharPositionGps(pIn+offset,'.',len-offset);
		offset++;
	
		temp2=pub_DecAscToU32_BitNum(pIn+offset,6,1,&BitNum);
		offset+=BitNum;

		//temp1=2230
		//temp2=282411
		//IntPart=22000000
		IntPart= (temp1/100)*1000000;
		if(BitNum==2)		DecPart=(temp1%100)*1000000 + temp2*10000;
		else if(BitNum==3)	DecPart=(temp1%100)*1000000 + temp2*1000;
		else if(BitNum==4)	DecPart=(temp1%100)*1000000 + temp2*100;
		else if(BitNum==5)	DecPart=(temp1%100)*1000000 + temp2*10;
		else if(BitNum==6)	DecPart=(temp1%100)*1000000 + temp2;
		else	return GD_ERR;

		//DecPart=30 282411
		//Latitude=22504706
		pRMC->Latitude = (u32)(IntPart + DecPart/60.0);
	}
	//N/S
	if(pub_FieldCheckGps(&offset,pIn,end,GPS_GPRMC_FIELD_NS)==GD_ERR)
		return GD_ERR;	
	if(*(pIn+offset)==',') 	pRMC->NS='0';
	else					pRMC->NS = pIn[offset];
	if(pRMC->NS=='S')
			pRMC->Latitude|=0x80000000;
	else	pRMC->Latitude&=0xEFFFFFFF;
	
	//Longtitude
	if(pub_FieldCheckGps(&offset,pIn,end,GPS_GPRMC_FIELD_LONGTITUDE)==GD_ERR)
		return GD_ERR;
	if(*(pIn+offset)==',') 
		pRMC->Longitude = 0;
	else
	{
		//12021.77782
		u32 temp1=0,temp2=0;
		double IntPart=0,DecPart=0;
		u8  BitNum=0;
		
		temp1=pub_DecAscToU32(pIn+offset,5,1);
		offset+=5;
		
		offset += pub_GetCharPositionGps(pIn+offset,'.',len-offset);
		offset++;

		temp2=pub_DecAscToU32_BitNum(pIn+offset,6,1,&BitNum);
		offset+=BitNum;
		
		IntPart= (temp1/100)*1000000;
		if(BitNum==2)		DecPart=(temp1%100)*1000000 + temp2*10000;
		else if(BitNum==3)	DecPart=(temp1%100)*1000000 + temp2*1000;
		else if(BitNum==4)	DecPart=(temp1%100)*1000000 + temp2*100;
		else if(BitNum==5)	DecPart=(temp1%100)*1000000 + temp2*10;
		else if(BitNum==6)	DecPart=(temp1%100)*1000000 + temp2;
		else	return GD_ERR;
		
		pRMC->Longitude = (u32)(IntPart + DecPart/60.0);
	}
	
	//E/W
	if(pub_FieldCheckGps(&offset,pIn,end,GPS_GPRMC_FIELD_EW)==GD_ERR)
		return GD_ERR;	
	if(*(pIn+offset)==',') 	pRMC->EW ='0';
	else					pRMC->EW = pIn[offset];
	if(pRMC->EW=='W')
			pRMC->Longitude|=0x80000000;
	else	pRMC->Longitude&=0xEFFFFFFF;
	
	//SPEED
	if(pub_FieldCheckGps(&offset,pIn,end,GPS_GPRMC_FIELD_SPEED)==GD_ERR)
		return GD_ERR;	
	
	pRMC->Speed = 0;
	if(*(pIn+offset)==',') 	pRMC->Speed =0;
	else
	{
		while((*(pIn+offset)>='0')&&(*(pIn+offset)<='9'))
		{
			pRMC->Speed *= 10;
			pRMC->Speed += *(pIn+offset)-'0';
			offset ++;
		}
		if(*(pIn+offset)=='.')
		{
			u8 t;
			offset++;
			for(t=0;t<3;t++)
			{
				pRMC->Speed *= 10;
				if((*(pIn+offset)>='0')&&(*(pIn+offset)<='9'))
				{
					pRMC->Speed += *(pIn+offset)-'0';
					offset++;
				}
			}
		}
		else	pRMC->Speed *= 1000;

		if(pRMC->Speed>216000)
			return GD_ERR;
		
	}
	
	//DIRECTION
	if(pub_FieldCheckGps(&offset,pIn,end,GPS_GPRMC_FIELD_DIRECTION)==GD_ERR)
		return GD_ERR;	
	if(*(pIn+offset)==',') 	pRMC->Direction =0;
	else
	{
		pRMC->Direction = (((u16)pub_DecAscToU32(pIn+offset,10,1))*10);
		offset += pub_GetCharPositionGps(pIn+offset,'.',len-offset);
		offset++;
		pRMC->Direction+=pub_DecAscToU32(pIn+offset,1,1);

		if(pRMC->Direction>3600)
			return GD_ERR;
	}
	iSeg = pRMC->Direction;
	
	//Date
	if(pub_FieldCheckGps(&offset,pIn,end,GPS_GPRMC_FIELD_DATE)==GD_ERR)
		return GD_ERR;	
	if(*(pIn+offset)==',')	
	{
		pRMC->Time.Year=0;
		pRMC->Time.Mon=0;
		pRMC->Time.Day=0;
	}
	else
	{
		pRMC->Time.Day =0;
		pRMC->Time.Day =pub_DecAscToU32(pIn+offset,2,1);
		offset+=2;
		
		pRMC->Time.Mon=0;
		pRMC->Time.Mon=pub_DecAscToU32(pIn+offset,2,1);
		offset+=2;
		
		pRMC->Time.Year =0;
		pRMC->Time.Year =pub_DecAscToU32(pIn+offset,2,1);
		offset+=2;
	}
	pIn[end] = 0x00;
	return GD_OK;
}


备注说明:因版面有限,GGAGSA等数据帧的解析请参考RMC


    

通信模块初始化流程图

     点击查看大图

通信模块初始化源码:


bool gsm_mng_gsm_init(void)
{
	static u8 fail_cnt = 0;
	u8 cmd_index;
	
	gsm_mng_info_ptr()->flags.clr_recvbuff = TRUE;
	if(gsm_mng_module_pwrkeyon() == FALSE) return(FALSE);
	
	gsm_atcmd_waitack(NULL,NULL,NULL,0);
	if(gsm_mng_wait_ready() == FALSE)
	{
		scom_test_set(TEST_GSM_MODULE,TEST_GSM_FAIL);
		return(FALSE);
	}
	for(cmd_index = 0; cmd_index < GSM_INIT_CMD_LIST; cmd_index ++)
	{
		if(Gsm_Sim800L_init[cmd_index]() == FALSE)
		{
			uprintf(GSM,"Gsm Init fail, restart module!\r\n");
			if(cmd_index == 4) GSM_LED_CTRL(LED_STA_GLITTER_1);
			if(++fail_cnt >= 5) fail_cnt = 5;
			OSTimeDly(TASK_DLY_1S*fail_cnt);
			return(FALSE);
		}
		scom_test_set(TEST_GSM_MODULE,TEST_GSM_INFO);
		OSTimeDly(TASK_DLY_01S);
		if(cmd_index > 4)
		{
			GSM_LED_CTRL(LED_STA_GLITTER_2);
		}
		
		#if GSM_OPER_REG
		if(cmd_index == 7)
		{
			scom_test_set(TEST_GSM_MODULE,TEST_GSM_CREG);
			if(gsm_mng_gsm_regstatus() == FALSE) return(FALSE);
			scom_test_set(TEST_GSM_MODULE,TEST_GSM_INIT);
		}
		#endif
	}
	fail_cnt = 0;
	return(TRUE);
}

static const GSM_ATCMD_FUNC Gsm_Sim800L_init[GSM_INIT_CMD_LIST] =
{
	gsm_atcmd_ATE0,
	gsm_atcmd_IPR,
	gsm_atcmd_CGMM,
	gsm_atcmd_CGMR,
	gsm_atcmd_CGSN,
	gsm_atcmd_CPIN,
	gsm_atcmd_CIMI,
	gsm_atcmd_CCID,
	
	#if GSM_OPER_REG
	gsm_atcmd_CREG0,
	gsm_atcmd_COPS,
	#endif
	gsm_atcmd_CMEE,
	gsm_atcmd_CLIP,
	gsm_atcmd_CMGF,
	gsm_atcmd_CNMI
};

/*
-------------------------------------------------------------------------------------------------
-函数功能:	ATE 设置回显命令
-参数说明:	
-------------------------------------------------------------------------------------------------
*/
bool gsm_atcmd_ATE0(void)
{
	gsm_atcmd_package("ATE0\r\n",strlen("ATE0\r\n"));
	return(gsm_atcmd_waitack(NULL,"OK",NULL,5));
}


 

 

IO口模拟串口

simulateuart_drv.c

#include "stm8s_conf.h"
#include "simulateuart_drv.h"
#include "drv_hal.h"

#if defined(SUPPORT_SIMULATE_UART1) || defined(SUPPORT_SIMULATE_UART2)
u8 gSimulateUartFlag = 0;

void SimulateUartDelayms(u16 t)
{
    u16 i = 1000;
    while(t--)
    {
        while(i--);
    }
}
#endif

#ifdef SUPPORT_SIMULATE_UART1

#define SIM_UART1_GetTxFlagStatus() (SIMULATE_UART1_TX_FLAG & gSimulateUartFlag)
#define SIM_UART1_SetTxFlagStatus() (gSimulateUartFlag |= SIMULATE_UART1_TX_FLAG)
#define SIM_UART1_ClsTxFlagStatus() (gSimulateUartFlag &= (~SIMULATE_UART1_TX_FLAG))

#define SIM_UART1_SetRxFlagStatus() (gSimulateUartFlag |= SIMULATE_UART1_RX_FLAG)
#define SIM_UART1_ClsRxFlagStatus() (gSimulateUartFlag &= (~SIMULATE_UART1_RX_FLAG))

#define SIM_UART1_GetRxINFlagStatus() (SIMULATE_UART1_RXIN_FLAG & gSimulateUartFlag)
#define SIM_UART1_SetRxINFlagStatus() (gSimulateUartFlag |= SIMULATE_UART1_RXIN_FLAG)
#define SIM_UART1_ClsRxINFlagStatus() (gSimulateUartFlag &= (~SIMULATE_UART1_RXIN_FLAG))

#if SUPPORT_SIMUART1_TX
static u8 gSimUart1SendData = 0;
#endif

#if SUPPORT_SIMUART1_RX
static u8 gSimUart1RcvData = 0;
#endif

extern void ScomReadData(u8 dat);
void SimulateUart1RxTxDrv(void)
{
    static u8 sendcnt = 0;
    static u8 sbitnum = 0;
    
#if SUPPORT_SIMUART1_RX
    static u8 rbitnum = 0;
    static u8 revcnt = 0;    

    if(SIM_UART1_GetRxINFlagStatus())
    {
        revcnt++;
        if((!((revcnt - 7) % 4)) && (revcnt >= 7))
        {
            if(rbitnum < 8)
            {
                if(MCU_RX_GET())
                {
                    gSimUart1RcvData |= (1 << rbitnum);
                }
                else
                {
                    gSimUart1RcvData &= (~(1 << rbitnum));
                }
            }
            else
            {
                revcnt = 0;
                rbitnum = 0;
                SIM_UART1_SetRxFlagStatus();
                SIM_UART1_ClsRxINFlagStatus();

                //串口设置
                ScomReadData(gSimUart1RcvData);
            }
            rbitnum++;
        }

        if(rbitnum > 7 && MCU_RX_GET())
        {
            revcnt = 0;
            rbitnum = 0;
            SIM_UART1_SetRxFlagStatus();
            SIM_UART1_ClsRxINFlagStatus();
        }
    }
    else
    {
        revcnt = 0;
        rbitnum = 0;
    }

#endif

#if SUPPORT_SIMUART1_TX
    if(SIM_UART1_GetTxFlagStatus())
    {
        if(++sendcnt < 4)
        {
            return;
        }

        sendcnt = 0;
        
        if(0 == sbitnum)
        {
            MCU_TX_CLS();
        }
        else if(sbitnum > 0 && sbitnum < 9)
        {
            if(gSimUart1SendData & 0x01)
            {
                MCU_TX_SET();
            }
            else
            {
                MCU_TX_CLS();  
            }
            gSimUart1SendData /= 2;
        }
        
        if(sbitnum >= 9)
        {        
            MCU_TX_SET();
            sbitnum = 0;
            SIM_UART1_ClsTxFlagStatus();        
        }

        sbitnum++;  
    }
    else
    {
        sbitnum = 0;
    }
#endif    
}

#if SUPPORT_SIMUART1_TX
void SimUart1_SendData8(u8 Data)
{
    while(SIM_UART1_GetTxFlagStatus())SimulateUartDelayms(1);    
    
    SIM_UART1_SetTxFlagStatus();    
    gSimUart1SendData = Data;
}

void SimUart1_SendStr(unsigned char *dat)
{
	while(*dat!='\0')
	{
		SimUart1_SendData8(*dat);
		dat++;
	}
}

void SimUart1_SendBytes(unsigned char *buf , u16 len)
{
    u16 i = 0;
	while(i < len)
	{
		SimUart1_SendData8(buf[i++]);
	}
}

#endif

#if SUPPORT_SIMUART1_RX
//u8 SimUART1_ReceiveData8(void)
//{
//    SIM_UART1_ClsRxFlagStatus();
//    return (u8)gSimUart1RcvData;
//}

void SimUART1_RCV_isr(void)
{
   if(!MCU_RX_GET())
   {
        SIM_UART1_SetRxINFlagStatus();
   }
}
#endif

#endif/*SUPPORT_SIMULATE_UART1*/

#ifdef SUPPORT_SIMULATE_UART2

#define SIM_UART2_GetTxFlagStatus() (SIMULATE_UART2_TX_FLAG & gSimulateUartFlag)
#define SIM_UART2_SetTxFlagStatus() (gSimulateUartFlag |= SIMULATE_UART2_TX_FLAG)
#define SIM_UART2_ClsTxFlagStatus() (gSimulateUartFlag &= (~SIMULATE_UART2_TX_FLAG))

#define SIM_UART2_SetRxFlagStatus() (gSimulateUartFlag |= SIMULATE_UART2_RX_FLAG)
#define SIM_UART2_ClsRxFlagStatus() (gSimulateUartFlag &= (~SIMULATE_UART2_RX_FLAG))

#define SIM_UART2_GetRxINFlagStatus() (SIMULATE_UART2_RXIN_FLAG & gSimulateUartFlag)
#define SIM_UART2_SetRxINFlagStatus() (gSimulateUartFlag |= SIMULATE_UART2_RXIN_FLAG)
#define SIM_UART2_ClsRxINFlagStatus() (gSimulateUartFlag &= (~SIMULATE_UART2_RXIN_FLAG))

#if SUPPORT_SIMUART2_TX
static u8 gSimUart2SendData = 0;
#endif

#if SUPPORT_SIMUART2_RX
static u8 gSimUart2RcvData = 0;
#endif

extern void GpsReadData_Analyze(u8 dat);
void SimulateUart2RxTxDrv(void)
{
    static u8 sendcnt = 0;
    static u8 sbitnum = 0;

#if SUPPORT_SIMUART2_RX
    static u8 rbitnum = 0;
    static u8 revcnt = 0;    

    if(SIM_UART2_GetRxINFlagStatus())
    {
        revcnt++;
        if((!((revcnt - 7) % 4)) && (revcnt >= 7))
        {
            if(rbitnum < 8)
            {
                if(GPS_RX_GET())
                {
                    gSimUart2RcvData |= (1 << rbitnum);
                }
                else
                {
                    gSimUart2RcvData &= (~(1 << rbitnum));
                }
            }
            else
            {
                revcnt = 0;
                rbitnum = 0;
                SIM_UART2_SetRxFlagStatus();
                SIM_UART2_ClsRxINFlagStatus();
            }
            rbitnum++;
        }

        if(rbitnum > 7 && GPS_RX_GET())
        {
            revcnt = 0;
            rbitnum = 0;
            SIM_UART2_SetRxFlagStatus();
            SIM_UART2_ClsRxINFlagStatus();
            
            GpsReadData_Analyze(gSimUart2RcvData);
        }
    }
    else
    {
        revcnt = 0;
        rbitnum = 0;
    }

#endif

#if SUPPORT_SIMUART2_TX
    if(SIM_UART2_GetTxFlagStatus())
    {
        if(++sendcnt < 4)
        {
            return;
        }

        sendcnt = 0;
        
        if(0 == sbitnum)
        {
            GPS_TX_CLS();
        }
        else if(sbitnum > 0 && sbitnum < 9)
        {
            if(gSimUart1SendData & 0x01)
            {
                GPS_TX_SET();
            }
            else
            {
                GPS_TX_CLS();  
            }
            gSimUart1SendData /= 2;
        }
        
        if(sbitnum >= 9)
        {        
            GPS_TX_SET();
            sbitnum = 0;
            SIM_UART2_ClsTxFlagStatus();        
        }

        sbitnum++;  
    }
    else
    {
        sbitnum = 0;
    }
#endif
}

#if SUPPORT_SIMUART2_TX
void SimUart2_SendData8(u8 Data)
{
    while(SIM_UART2_GetTxFlagStatus())SimulateUartDelayms(1);    
    
    SIM_UART2_SetTxFlagStatus();    
    gSimUart1SendData = Data;
}
#endif

#if SUPPORT_SIMUART2_RX
//u8 SimUART2_ReceiveData8(void)
//{
//    SIM_UART2_ClsRxFlagStatus();
//    return (u8)gSimUart2RcvData;
//}

void SimUART2_RCV_isr(void)
{
   if(!GPS_RX_GET())
   {
        SIM_UART2_SetRxINFlagStatus();
   }
}
#endif

#endif

 

simulateuart_drv.h 


#ifndef __SIMULATE_UART_H__
#define __SIMULATE_UART_H__

//#define SUPPORT_SIMULATE_UART1
#define SUPPORT_SIMULATE_UART2

#if defined(SUPPORT_SIMULATE_UART1) || defined(SUPPORT_SIMULATE_UART2)
extern u8 gSimulateUartFlag;
#endif

#ifdef SUPPORT_SIMULATE_UART1
#define SUPPORT_SIMUART1_TX             1
#define SUPPORT_SIMUART1_RX             1
#define SIMULATE_UART1_TX_FLAG          (u8)(1 << 0)
#define SIMULATE_UART1_RX_FLAG          (u8)(1 << 1)
#define SIMULATE_UART1_RXIN_FLAG        (u8)(1 << 2)

#define SIM_UART1_GetRxFlagStatus() (SIMULATE_UART1_RX_FLAG & gSimulateUartFlag)

void SimUart1_SendData8(u8 Data);
void SimUart1_SendStr(unsigned char *dat);
//u8 SimUART1_ReceiveData8(void);
void SimulateUart1RxTxDrv(void);
void SimUART1_RCV_isr(void);
void SimUart1_SendBytes(unsigned char *buf , u16 len);
#else
#define SimUART1_RCV_isr()/\
/
#define SimulateUart1RxTxDrv()/\
/
#endif

#ifdef SUPPORT_SIMULATE_UART2
#define SUPPORT_SIMUART2_TX            0
#define SUPPORT_SIMUART2_RX            1

#define SIMULATE_UART2_TX_FLAG      (1 << 3)
#define SIMULATE_UART2_RX_FLAG      (1 << 4)
#define SIMULATE_UART2_RXIN_FLAG    (1 << 5)

#define SIM_UART2_GetRxFlagStatus() (SIMULATE_UART2_RX_FLAG & gSimulateUartFlag)

void SimUart2_SendData8(u8 Data);
//u8 SimUART2_ReceiveData8(void);
void SimulateUart2RxTxDrv(void);
void SimUART2_RCV_isr(void);

#else
#define SimUART2_RCV_isr()/\
/
#define SimulateUart2RxTxDrv()/\
/
#endif


#endif/*__SIMULATE_UART_H__*/


六、作品演示

视频地址 https://v.qq.com/x/page/f0535tupadh.html


七、总结

非常感谢主办方提供的这样一个技术交流平台,希望后续能继续举办类似的活动。在这样一个平台下能了较为全面的了解当前的电子产品设计方向与主流技术。在这样一个平台上可以学习更多的设计技巧与思路。每个参赛者都从各个方面、各类产品中不同程度的分享了自己所在领域的特色技术。这间接或直接的推进了电子技术的进一步发展,也让更多的专业人士、电子爱好者参与到了电子设计中。这也使得这个群体从各个层面上体验、体会到了电子设计的乐趣与价值。


本设计之初是一个只具备单纯定位功能的GNSS跟踪设备。后因为客户增加了特殊的功能,需要较多的内存来实现特定的算法,所以将MCU更换为STM32F042。但之前选用的STM8S003作为单纯定位功能的产品还是够用的。如果选用STM8S003为主控芯片需要使用IO口模拟一个串口来接收GPS数据。这部分功能已经调通并且使用了容错算法,因此误码率很低。实测通信速率为9600bps时几乎不会误码。为方便各位参考特分享了这段代码!但同时郑重声明:未经本人许可,其它人不能将以上设计和源码直接使用到商业产品中。



主题

回复
发表于2017-08-07 16:09:06   |  显示全部楼层
11#
给隔壁女神的鞋子下面装一个

主题

回复
  • 温馨提示: 标题不合格、重复发帖、发布广告贴,将会被删除帖子或禁止发言。 详情请参考: 社区发帖规则
  • 您当前输入了 0 个文字。还可以输入 8000 个文字。 已添加复制上传图片功能,该功能目前仅支持chrome和火狐

禁言/删除

X
请选择禁言时长:
是否清除头像:
禁言/删除备注:
昵 称:
 
温馨提示:昵称只能设置一次,设置后无法修改。
只支持中文、英文和数字。

举报

X
请选择举报类型:
请输入详细内容:

顶部