标题:
51单片机GPS报时器程序问题求助
[打印本页]
作者:
wsdwhb
时间:
2022-10-4 19:51
标题:
51单片机GPS报时器程序问题求助
本人是一名业余无线电爱好者,最近想着给本地朋友做一套中继台的信标系统,就是整点报时加语音提示,想了好多方案,差了好多资料,最后决定用GPS授时,单片机读取时间,然后比较,再通过串口输出指令来控制MP3播放模块,现在问题是,GPS读取时间已经完成,串口整点发指令正常,唯独是,只能发一次指令,发一次指令后,单片机不再读取更新时间,就无法进行下一个时间的报时,请大家多多指点,我没学过单片机,程序都是抄的,不好意思了。
#include "stc15.h"
#define LEDPORT P2
typedef unsigned char uint8;//
#define uint unsigned int
sbit D1=P4^1;
sbit D2=P4^2;
sbit D3=P4^4;
sbit D4=P4^5;
sbit LED=P3^6;
sbit LED1=P3^7;
sbit play=P3^3;
unsigned char h,hour,min,sec;
bit rev_start,rev_stop;
unsigned char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//0-9,
unsigned char code fs[]={0x7e,0x04,0x41,0x00,0x01,0xef};//播放器发送指令
unsigned char buf[80]; //请把GPS那货发来的数据放到我的肚子里
void delayms(int ms)
{
int i,j;
for(i=ms;i>0;i--)
for(j=845;j>0;j--);
}
void TimerInit()
{
TMOD=0x21;
TH0 = 0xF1; //4ms左右
TL0 = 0x9A;
ET0=1;
TR0=1;
SCON = 0x50;//使用串行工作方式1,10位异步收发8位数据,波特率可变(由T1的溢出率控制)
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE0; //设置定时初始值
TH1 = 0xFE; //设置定时初始值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
ES = 1;
EA=1;
}
void Display(unsigned char hour,min) //数码管显示
{
static unsigned char i;
LEDPORT=0xff;
switch (i)
{
case 0: if(hour/16) LEDPORT=tab[hour/16];
else LEDPORT=tab[10]; D1=0;D2=D3=D4=1;break;
case 1: LEDPORT=tab[hour%16]; D2=0;D1=D3=D4=1;break;
case 2: LEDPORT=tab[min/16]; D3=0;D1=D2=D4=1;break;
case 3: LEDPORT=tab[min%16]; D4=0;D2=D3=D1=1;break;
}
i++;
if(i==4)i=0;
}
void Timer0() interrupt 1
{
TH0 = 0xF1;
TL0 = 0x9A;
Display(hour,min);//定时器兄弟简单而单调的工作,很轻松的。每4ms刷新下数码管,全年无休哦
}
/*********************串口发送*******************************/
void fasong()
{
TI=0;
for(h=0;h<6;h++)
{
SBUF=fs[h];
delayms(5);
TI=0;
}
}
/*************************串口数据接收**************************/
void Uart_Receive(void) interrupt 4
{
unsigned char ch,num;
ES = 0;
if (RI)//如果接收完成则进入
{
ch = SBUF;
if (ch == '$') //如果收到字符'$',便开始接收
{
rev_start = 1;
rev_stop = 0; //接收停止标志
}
if (rev_start == 1) //标志位为1,开始接收
{
buf[num++] = ch; //字符存到数组中
if (ch == '\n') //如果接收到换行
{
buf[num] = '\n';
rev_start = 0;
rev_stop = 1; //接收停止标志
num = 0;
if( hour==0x07 && min==0x00 && sec==0x00) //早上7点
{
fasong(); //发送播放指令前4字节 (头帧及命令帧)
delayms(5);
SBUF=0x01; //发送播放指令第5字节(第一首)
delayms(5);
SBUF=0xef; //发送播放指令前6字节(尾帧)
}
if( hour==0x08 && min==0x00 && sec==0x00) //上午8点
{
fasong();
delayms(5);
SBUF=0x02;
delayms(5);
SBUF=0xef;
}
if( hour==0x09 && min==0x00 && sec==0x00) //上午9点
{
fasong();
delayms(5);
SBUF=0x03;
delayms(5);
SBUF=0xef;
}
if( hour==0x10 && min==0x00 && sec==0x00) //上午10点
{
fasong();
delayms(5);
SBUF=0x04;
delayms(5);
SBUF=0xef;
}
if( hour==0x11 && min==0x00 && sec==0x00) //上午11点
{
fasong();
delayms(5);
SBUF=0x05;
delayms(5);
SBUF=0xef;
}
if( hour==0x12 && min==0x00 && sec==0x00) //中午12点
{
fasong();
delayms(5);
SBUF=0x06;
delayms(5);
SBUF=0xef;
}
if( hour==0x13 && min==0x00 && sec==0x00) //下午1点
{
fasong();
delayms(5);
SBUF=0x07;
delayms(5);
SBUF=0xef;
}
if( hour==0x14 && min==0x00 && sec==0x00) //下午2点
{
fasong();
delayms(5);
SBUF=0x08;
delayms(5);
SBUF=0xef;
}
if( hour==0x15 && min==0x00 && sec==0x00) //下午3点
{
fasong();
delayms(5);
SBUF=0x09;
delayms(5);
SBUF=0xef;
}
if( hour==0x14 && min==0x00 && sec==0x00) //下午4点
{
fasong();
delayms(5);
SBUF=0x0a;
delayms(5);
SBUF=0xef;
}
if( hour==0x17 && min==0x54 && sec==0x00) //下午5点
{
fasong();
delayms(5);
SBUF=0x0b;
delayms(5);
SBUF=0xef;
}
if( hour==0x18 && min==0x00 && sec==0x00) //晚上6点
{
fasong();
delayms(5);
SBUF=0x0c;
delayms(5);
SBUF=0xef;
}
if( hour==0x19 && min==0x00 && sec==0x00) //晚上7点
{
fasong();
delayms(5);
SBUF=0x0d;
delayms(5);
SBUF=0xef;
}
if( hour==0x20 && min==0x00 && sec==0x00) //晚上8点
{
fasong();
delayms(5);
SBUF=0x0e;
delayms(5);
SBUF=0xef;
}
if( hour==0x21 && min==0x00 && sec==0x00) //晚上9点
{
fasong();
delayms(5);
SBUF=0x0e;
delayms(5);
SBUF=0xef;
}
if( hour==0x22 && min==0x00 && sec==0x00) //晚上10点
{
fasong();
delayms(5);
SBUF=0x0f;
delayms(5);
SBUF=0xef;
}
}
}
RI = 0; //RI清0,重新接收
ES = 1; //串口1中断允许
}
if(TI)
{
TI = 0;
}
}
void main()
{
LED1=0;
P0M0=0X00;P0M1=0X00;
P1M0=0X00;P1M1=0X00;
P2M0=0X00;P2M1=0X00;
P3M0=0X00;P3M1=0X00;
P4M0=0X00;P4M1=0X00;
TimerInit();
while(1)
{
if((rev_stop==1)&&(buf[5]=='A'))//如果接收到GNGGA
{
ES=0;
hour= (buf [7]-0x30)* 16+ buf[8] -0x30;
min= (buf [9]-0x30)* 16+ buf[10]-0x30;
sec= (buf[11]-0x30)* 16+ buf[12]-0x30;
hour= hour / 16 * 10 + hour % 16;
LED=!LED;
LED1=!LED1;
hour= (hour+8) % 24;//UTC Time换算成北京时间
hour=hour/10*16+hour%10;
ES=1;
rev_stop=0;
}
}
}
作者:
devcang
时间:
2022-10-5 11:49
原逻辑,最大的问题:如果buf[5]=='A'不成立,不会再接收GPS讯号。
程序当中,有建议的地方,使用//!!注释了
//
http://www.51hei.com/bbs/dpj-223997-1.html
// GPS 定时报时
#include "stc15.h"
typedef unsigned char uint8;//
#define uint unsigned int
#define LEDPORT P2
sbit D1 =P4^1;
sbit D2 =P4^2;
sbit D3 =P4^4;
sbit D4 =P4^5;
sbit LED =P3^6;
sbit LED1=P3^7;
sbit play=P3^3;
unsigned char num=0; //!!这个是全局变量,不要定义在中断函数内
unsigned char hour, min, sec;
bit rev_start, rev_stop, uartBusy=0;
unsigned char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//0-9,
unsigned char code fs[] ={0x7e,0x04,0x41,0x00,0x01,0xef};//播放器发送指令
unsigned char buf[80]; //请把GPS那货发来的数据放到我的肚子里
void delayms(int ms){
int i,j;
for(i=ms;i>0;i--)
for(j=845;j>0;j--);
}
void TimerInit(){
TMOD = 0x21;
TH0 = 0xF1; //4ms左右
TL0 = 0x9A;
ET0 = 1;
TR0 = 1;
SCON = 0x50; //使用串行工作方式1,10位异步收发8位数据,波特率可变(由T1的溢出率控制)
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE0; //设置定时初始值
TH1 = 0xFE; //设置定时初始值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
ES = 1;
EA = 1;
}
void Display(unsigned char hour,min){ //数码管显示
static unsigned char iDisp; //!!原来是i,没意义,变量名太短、还容易混淆
LEDPORT=0xff;
switch (iDisp){
case 0: if(hour/16) LEDPORT=tab[hour/16];
else LEDPORT=tab[10]; D1=0;D2=D3=D4=1;break;
case 1: LEDPORT=tab[hour%16]; D2=0;D1=D3=D4=1;break;
case 2: LEDPORT=tab[min/16]; D3=0;D1=D2=D4=1;break;
case 3: LEDPORT=tab[min%16]; D4=0;D2=D3=D1=1;break;
}
iDisp++;
if(iDisp==4)iDisp=0;
}
void Timer0() interrupt 1{
TH0 = 0xF1;
TL0 = 0x9A;
Display(hour, min);//定时器兄弟简单而单调的工作,很轻松的。每4ms刷新下数码管,全年无休哦
}
/*********************串口发送*******************************/
void uartByte(unsigned char c){//统一串口发送
uartBusy=1;
SBUF=c;
while(uartBusy==1); //!!延时的串口处理不好
}
void faSongHead(){
unsigned char i; //!!局部变量,在局部定义
for(i=0; i<6; i++){
uartByte(fs[i]);
}
}
/*************************串口数据接收**************************/
void Uart_Receive(void) interrupt 4{
unsigned char ch;
ES = 0;
if (RI){ //如果接收完成则进入
ch = SBUF;
if (ch == '
){ //如果收到字符'
,便开始接收
rev_start = 1;
rev_stop = 0; //接收停止标志
}
if (rev_start == 1){ //标志位为1,开始接收
buf[num++] = ch; //字符存到数组中
if (ch == '\n'){ //如果接收到换行
// buf[num] = '\n'; //!!没意义,不赋值
rev_start = 0;
rev_stop = 1; //接收停止标志
}
}
RI = 0; //RI清0,重新接收
}
if(TI){
TI = 0;
uartBusy = 0;
}
}
void main(){
delayms(10); //适当延时,稳定一下
LED1=0;
P0M0=0X00; P0M1=0X00;
P1M0=0X00; P1M1=0X00;
P2M0=0X00; P2M1=0X00;
P3M0=0X00; P3M1=0X00;
P4M0=0X00; P4M1=0X00;
TimerInit();
while(1){
if(rev_stop==1){
ES = 0;
//!!原最大的问题:如果buf[5]=='A'不成立,不会再接收GPS讯号。
if(buf[5]=='A'){//如果接收到GNGGA
hour = (buf[ 7]-0x30)* 16+ buf[ 8]-0x30;
min = (buf[ 9]-0x30)* 16+ buf[10]-0x30;
sec = (buf[11]-0x30)* 16+ buf[12]-0x30;
hour = hour / 16 * 10 + hour % 16;
LED = !LED;
LED1 = !LED1;
hour = (hour+8) % 24;//UTC Time换算成北京时间
hour = hour/10*16+hour%10;
//!!不要放在中断中处理
if( (hour>6 && hour<23) && min==0x00 && sec==0x00){ //早上7~22点
faSongHead(); //发送播放指令前4字节 (头帧及命令帧)
delayms(5);
//SBUF=0x01; //发送播放指令第5字节(第一首)
uartByte(hour-6); //发送播放指令第5字节(第一首)!!规律的判断,用加减法
uartByte(0xef); //发送播放指令前6字节(尾帧)!!延时的串口处理不好
}
}
num = 0; //接收缓冲计数器
rev_stop=0;
ES = 1;
}
}
}
复制代码
作者:
devcang
时间:
2022-10-5 11:52
请看附件
~~~~~~~~~~~~~~~
STC15_gps_time.zip
2022-10-5 11:52 上传
点击文件名下载附件
2.19 KB, 下载次数: 14
作者:
yzwzfyz
时间:
2022-10-8 10:23
写程序最好要有自己的构思。
一次成功了,理论上再重新一定要过一次不就OK的吗。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1