GPS_C51_程序
- 格式:pdf
- 大小:93.19 KB
- 文档页数:6
这其中包括1602 驱动头文件,和解析主程序,使用时分开粘贴到对应的文件中/*LCD1602驱动,兼容LCD2402*/sbit LCD_DB0= P0A0;sbit LCD_DB1=卩0人1;sbit LCD_DB2= P0A2;sbit LCD_DB3= P0A3;sbit LCD_DB4= P0A4;sbit LCD_DB5= P0A5;sbit LCD_DB6= P0A6;sbit LCD_DB7= P0A7;sbit LCD1602_RS=P2A4;sbit LCD1602_RW=P2A5;sbit LCD1602_EN=P2A6;void LCD_write_char( unsigned x,unsigned char y,unsigned char dat); 0f0f8F0c0c0c,'0'}; ");LCD_write_string(0,1,"Please Check.."); while(buf_full==0);LCD_cls(); dsp_count=0;}}else{ ;for(i=3;i<10;i++){ LCD_write_char(i+2,0,JD[i]);}LCD_write_char(0,1,WD_a); ;for(i=2;i<9;i++){ LCD_write_char(i+3,1,WD[i]);}}LCD_write_char(14,1,use_sat[0]); ;for(i=3;i<10;i++){LCD_write_char(i+2,0,JD[i]);}LCD_write_char(0,1,WD_a); ;for(i=2;i<9;i++){LCD_write_char(i+3,1,WD[i]);}}LCD_write_char(14,0,use_sat[0]);dot_count++;elsebreak ;}switch(dot_count){case 1:b=((speed[0]-'0')*10+(speed[2]-'0'))*;break;case 2:b=((speed[0]-'0')*100+(speed[1]-'0')*10+(speed[4]-'0'))*;break;case 3:b=((speed[0]-'0')*1000+(speed[1]-'0')*100+(speed[2]-'0')*10+(speed[4]-'0'))*; break;}if(b>maxspeed){maxspeed=b;}/*************************************最大速度处理*************************************/if(count<10)for(i=0;i<5;i++){ LCD_write_char(i,0,speed[i]);; hspeed[4]=maxspeed%10+0x30;count++;LCD_write_string(5,0,"Km/hA");LCD_write_char(0,0,hspeed[0]);LCD_write_char(1,0,hspeed[1]);LCD_write_char(2,0,hspeed[2]);LCD_write_char(3,0,hspeed[3]);LCD_write_char(4,0,hspeed[4]); }// 最大速度显*/ /*******************************************************************************/ for(i=0;i<5;i++){LCD_write_char(11+i,0,angle[i]); }} buf_full&=~0x04; dsp_count=0;}}}}}bit chk_key(void){if(!KEY1){delayms(10);if(!KEY1){ while(!KEY1); delayms(10); return(1);}}LCD_cls(); // 清屏return(0);// 系统初始化void sys_init() { unsigned char i; SCON = 0x50;TMOD = 0x21;if(GPS_SPD){ TH1 = 0xfa;}else{TH1 =0xfd; } TR1 = 1;LCD_init(8); /* SCON: mode 1, 8-bit UART, enable rcvr *//* TMOD: timer 1, mode 2, 8-bit reload *//* TH1: reload value for 9600 baud @ *//* TH1: reload value for 4800 baud @ *//* TR1: timer 1 run */// 初始化LCDLCD_write_string(0,0," GPS SIRF II 2 ");LCD_write_string(0,1," 11-11-23 1342 ");for(i=1;i<4;i++){delayms(250); }//LCD_cls();IE=0x90;}// 开总中断、串口中断// 串口接收中断void uart(void) interrupt 4{unsigned char tmp;if(RI){ tmp=SBUF;switch(tmp){ case'$':cmd_number=0;mode=1;byte_count=0;break;case ',': seg_count++;byte_count=0; // 命令类型清空// 接收命令模式// 接收位数清空// 逗号计数加1break;1*1.switch(cmd_number){ case 1:buf_full|=0x01;break;case 2:buf_full|=0x02;break;case 3:buf_full|=0x04;break;}mode=0;break;default:if(mode==1){// 命令种类判断cmd[byte_count]=tmp; // 接收字符放入类型缓存if(byte_count>=4){ // 如果类型数据接收完毕,判断类型if(cmd[0]=='G'){ if(cmd[1]=='P'){ if(cmd[2]=='G'){if(cmd[3]=='G'){ if(cmd[4]=='A'){ cmd_number=1; mode=2;seg_count=0; byte_count=0;}}else if(cmd[3]=='S'){if(cmd[4]=='V'){ cmd_number=2; mode=2;seg_count=0; byte_count=0;}}}else if(cmd[2]=='R'){if(cmd[3]=='M'){ if(cmd[4]=='C'){ cmd_number=3;mode=2; seg_count=0; byte_count=0;}}}}}else if(mode==2){// 接收数据处理switch (cmd_number){case 1: // 类型1 数据接收。
c251定位控制用法
c251是一种经典的8位单片机,其定位控制用法指的是使用
c251单片机实现定位控制功能。
以下是使用c251进行定位控
制的一般步骤:
1. 系统设计:根据应用需求设计定位控制系统的硬件和软件结构,确定使用的传感器和执行器等。
2. 硬件连接:根据设计要求,将传感器和执行器连接到c251
单片机的GPIO口或外部中断输入口。
3. 编写驱动程序:根据所选的传感器和执行器规格,编写相应的驱动程序,用于读取传感器数据和控制执行器。
4. 数据采集和处理:通过编写中断服务程序或定时器中断程序,实时读取传感器数据,并进行必要的信号处理和滤波操作。
5. 控制算法实现:根据定位控制要求,选择合适的控制算法,并在主程序中编写相应的控制算法实现。
6. 实时控制输出:根据控制算法计算的结果,控制执行器输出相应的控制信号,实现精确的定位控制。
7. 调试和优化:通过实际测试和调试,对系统进行调整和优化,以确保定位控制的准确性和稳定性。
以上是使用c251实现定位控制的一般步骤,具体的实现细节和算法选择需要根据具体的应用场景和系统要求进行定制。
单片机解析GPS数据三、单片机解读GPS信息的程序设计用单片机解读GPS信息是GPS模块使用最重要的环节,由于汲设到产品的保密问题,这里只介绍时间的处理方法,而方位、速度的处理方法不做介绍,但通过时间的处理方法,同样可以处理方位、速度。
1、获取GPS模块的输出信息由于GPS模块每秒输出一次:$GPGGA 、$GPGSA、$GPGSV、$GPRMC数据。
速率慢,因此必须采用中断方式接收!(采用查询会造成数据丢失),而且单片机只需要处理$GPRMC信息,即可得到时间、方位、速度。
程序采用C51编制,在Keil C中编译!code unsigned char GPS_ASC[]="$GPRMC" ; //定义特征字符串unsigned char idata RsBuf[60];//**********************************************************//读取GPS模块串口数据, 采用中断方式void GetRs232_Data() interrupt 4{unsigned char i;unsigned int j;if (RI){RI=0;RsBuf[0]=SBUF;if (RsBuf[0] =='$'){ //是GPS数据的开始,进入查询接收for (i=1;i<sizeof(gps_asc)-1;i++){< p="">j=GetUartDat(); //接收下一个数据if (j<256) {RsBuf=(unsigned char)j;if (RsBuf!=GPS_ASC) return;}}//判别是否为$GPRMC数据,是继续接收!for (;i<sizeof(rsbuf);i++){< p="">j=GetUartDat();if (j<256) {RsBuf=(unsigned char)j;}else{break;}}// 接收完毕处理数据!if (1==JiaoYanDat(RsBuf)){FormatTimer(RsBuf); //格式化时间FormatSpeed(RsBuf); //处理速度}}}}// 2、接收数据的处理//数据处理前,必须要再次检验是否为$GPRMC信息。
物移防盗报警电路和程序一、功能说明物移防盗报警电路可以实现物体被移动时进行声光报警的功能。
二、电路功能简介物移防盗报警电路由电源、键盘、显示、物移检测、变调音效报警和单片机控制部分等电路组成。
初始时,电路处于解防状态,继电器断开,发光二极管每隔流水点亮。
.键盘和显示部分键为报警电路设防键,按下该键设防,所有发光二极管都点亮,电路进入设防状态。
键为报警电路解防键,按下该键解防,电路进入初始状态。
.物移检测电路进入设防状态后,若发生移动,.变调音效报警电路变调音效报警电路由两个定时器构成两个多谐振荡器组成,驱动喇叭可发出变调的声音当发生物体移动,物移检测电路送入单片机一个低电平信号,单片机检测到该信号后驱动继电器闭合,变调音效报警电路得电工作,发出报警声。
.电源部分使用直流电源为电路供电。
三、芯片介绍1.AT89S51 引脚如图所示。
引脚功能说明:()输入输出引脚(口线)~口位双向口,占~脚;~口位准双向口,占~脚;~口位准双向口,占~脚;~口位准双向口,占~脚;()控制口线脚:外部程序存储器读选通信号。
脚:地址锁存允许编程信号。
脚:外部程序存储器地址允许固化编程电压输入端。
脚:是复位信号输入端是备用电源输入端。
()电源及其它脚:电源端。
脚:接地端。
、~脚:时钟电路引脚。
当使用内部时钟时,这两个引脚端外接石英晶体和微调电容。
当使用外部时钟时,用于外接外部时钟源。
2.集成电路555 定时器是一种有记忆功能的器件,它既可以接成施密特触发器,又可以接成单稳态触发器和多谐振荡器。
图引脚图集成电路各管脚如图所示。
①引脚:公共地端为负极;②引脚:低触发端,低于/电源电压时即导通;③引脚:输出端,电流可达;④引脚:强制复位端,不用时可与电源正极相连或悬空;⑤引脚:用来调节比较器的基准电压,简称控制端,不用时可悬空,或通过电容器接地;⑥引脚:高触发端,也称阈值端,高于电源电压时即截止;⑦引脚:放电端;⑧引脚:电源正极。
51 单片机处理GPS 信号程序附录B:程序#include "display.h"GPS_INFO GPS; //GPS 信息结构体GPS 为结构体类型变量uchar code beiwei[] = "北纬";uchar code nanwei[] = "南纬";uchar code dongjing[] = "东经";uchar code xijing[] = "西经";uchar code sudu[] = "速度: ";uchar code hangxiang[] = "航向: ";uchar code gaodu[] = "高度: ";uchar code jiaodu[] = "角度: ";uchar code haiba[] = "海拔: ";uchar code du[] = "度";uchar code meter[] = "米";uchar code kmperhour[] = "km/h";uchar code date[] = " 年月日";void Show_Float(float fla, uchar x, uchar y);void GPS_DispTime(void){ uchari = 0;ucharch;char time[5];Lcd_DispLine(0, 0, date); //年月日Int_To_Str(GPS.D.year,time); //将年转换成字符串,存在time 中Lcd_SetPos(0, 0); //设置显示地址51 单片机处理GPS 信号程序if(strlen(time)==4) //判断接收数据是否有效,有效则显示{ i = 0;while(time[i] != '\0'){ ch = time[i++]; Lcd_WriteDat(ch); //显示年}}Int_To_Str(GPS.D.month,time);Lcd_SetPos(0, 3);if(strlen(time)==2) //判断接收数据是否有效,有效则显示{ i = 0;while(time[i] != '\0'){ ch =time[i++];Lcd_WriteDat(ch);}}Int_To_Str(GPS.D.day,time);Lcd_SetPos(0, 5);if(strlen(time)==2) //判断接收数据是否有效,有效则显示{ i = 0;while(time[i] != '\0'){ ch =time[i++];Lcd_WriteDat(ch);}}Int_To_Str(GPS.D.hour,time);Lcd_SetPos(1, 1);if(strlen(time)==2) //判断接收数据是否有效,有效则显示{ i = 0;while(time[i] != '\0'){ch =time[i++];Lcd_WriteDat(ch);}}Lcd_WriteDat(' ');Lcd_WriteDat(':');Int_To_Str(GPS.D.minute,time);Lcd_SetPos(1, 3); if(strlen(time)==2) //判断接收数据是否有效,有效则显示{ i = 0;while(time[i] != '\0'){ch =time[i++];Lcd_WriteDat(ch);}}Lcd_WriteDat(' ');Lcd_WriteDat(':');Int_To_Str(GPS.D.second,time);Lcd_SetPos(1, 5);if(strlen(time)==2) //判断接收数据是否有效,有效则显示{i = 0;while(time[i] != '\0'){ch =time[i++];Lcd_WriteDat(ch);}}}void GPS_DisplayOne(void) //第一屏{ucharch, i;char info[10];ET0=0; //T0 的溢出中断允许位,禁止T0 的溢出中断clr_screen();//Lcd_WriteCmd(0x01); //清屏GPS_DispTime(); //显示日期,时间if (GPS.NS == 'N') //判断是北纬还是南纬Lcd_DispLine(2, 0, beiwei);else if (GPS.NS == 'S')Lcd_DispLine(2, 0, nanwei);if (GPS.EW == 'E') //判断是东经还是西经Lcd_DispLine(3, 0, dongjing);else if (GPS.EW == 'W')Lcd_DispLine(3, 0, xijing);Int_To_Str(titude_Degree,info); //纬度Lcd_SetPos(2, 2);if(strlen(info)==2){ //只有正常显示纬度,才显示纬分i = 0;while(info[i] != '\0'){ ch = info[i++];Lcd_WriteDat(ch);}Lcd_WriteDat(' ');Lcd_WriteDat(' ');Lcd_WriteDat(0xA1);Lcd_WriteDat(0xE3); //显示度的符号Int_To_Str(titude_Cent,info); //纬分if(strlen(info)==2){ //只有正常显示纬分,才显示纬秒i = 0;while(info[i] != '\0'){ ch = info[i++];Lcd_WriteDat(ch);}Lcd_WriteDat(0xA1);Lcd_WriteDat(0xE4); //显示秒的符号Int_To_Str(titude_Second,info); //纬秒if(strlen(info)==2){ i = 0;while(info[i] != '\0'){ ch = info[i++];Lcd_WriteDat(ch);}}}}Int_To_Str(GPS.longitude_Degree,info); //经度if(strlen(info)==3){ Lcd_DispLine(3, 2, info);Lcd_WriteDat(' ');Lcd_WriteDat(0xA1); Lcd_WriteDat(0xE3);Int_To_Str(GPS.longitude_Cent,info); //经分if(strlen(info)==2){ Lcd_DispLine(3, 5, info);Lcd_WriteDat(0xA1);Lcd_WriteDat(0xE4);Int_To_Str(GPS.longitude_Second,info); //经秒if(strlen(info)==2){ Lcd_DispLine(3, 7, info);}}}ET0=1;}void GPS_DisplayTwo(void) //第二屏用于显示单位{ clr_screen();//Lcd_WriteCmd(0x01); //清屏ET0=0;Lcd_DispLine(0, 0, sudu);Lcd_DispLine(1, 0, hangxiang);Lcd_DispLine(2, 0, gaodu);Lcd_DispLine(3, 0, haiba);Show_Float(GPS.speed, 0, 3);Lcd_DispLine(0, 6, kmperhour);Show_Float(GPS.direction, 1, 3);Lcd_DispLine(1, 6, du);Show_Float(GPS.height_ground, 2, 3);Lcd_DispLine(2, 6, meter);Show_Float(GPS.height_sea, 3, 3);Lcd_DispLine(3, 6, meter);ET0=1;}void Show_Float(float fla, uchar x, uchar y){ intintegar;char Info[10],ch;uchari;Lcd_SetPos(x, y);integar = (int)fla; // 显示整数部分Int_To_Str(fla,Info); //显示整数部分i = 0;while(Info[i] !='\0'){ ch=Info[i++];Lcd_WriteDat(ch);}Lcd_WriteDat('.'); //显示小数点fla = fla - integar; //显示小数部分fla = fla * 10; //0.1 // 显示0.1integar = (int) fla; fla = fla - integar; // 改变fla 的值,使fla 总是小于1ch = integar + 0x30;Lcd_WriteDat(ch);fla = fla*10; //0.01 // 显示0.01integar = (int) fla;fla = fla - integar; // 改变fla 的值,使fla 总是小于1ch = integar + 0x30 ;Lcd_WriteDat(ch);}GPS 程序:#include "GPS.h"#include "LCD.h"#include <string.h>uchar code init1[] = {"BASE-MCU GPS 终端"};uchar code init2[] = {"商院电信091 班"};uchar code init3[] = {"GPS 初始化......"};uchar code init4[] = {"搜索定位卫星...."};static ucharGetComma(ucharnum,char* str);static double Get_Double_Number(char *s); //得到双精度的数据static float Get_Float_Number(char *s); //得到单精度的数据static void UTC2BTC(DATE_TIME *GPS); //格林时间到北京时间的转换void GPS_Init(void) //GPS 初始化{ Lcd_DispLine(0, 0, init1);Lcd_DispLine(1, 0, init2);Lcd_DispLine(2, 0, init3);Lcd_DispLine(3, 0, init4);}intGPS_RMC_Parse(char *line,GPS_INFO *GPS) //运输定位数据最大帧70 { //*GPS 为结构体类型的指针ucharch, status, tmp;float lati_cent_tmp, lati_second_tmp; //经度的分、秒临时变量float long_cent_tmp, long_second_tmp; //纬度的分、秒临时变量float speed_tmp; //速度的临时变量char *buf = line;ch = buf[5];status = buf[GetComma(2, buf)]; //定位状态给status,判断是否是A,if (ch == 'C') //如果第五个字符是C,($GPRMC)推荐最小定位信息{ if (status == 'A') //如果数据有效,则分析‘V’无效,‘A’有效{ GPS -> NS = buf[GetComma(4, buf)];GPS -> EW = buf[GetComma(6, buf)];GPS->latitude = Get_Double_Number(&buf[GetComma(3, buf)]); // 经度GPS->longitude = Get_Double_Number(&buf[GetComma(5, buf)]); //纬度GPS->latitude_Degree = (int)GPS->latitude / 100; //分离纬度lati_cent_tmp = (GPS->latitude - GPS->latitude_Degree * 100);GPS->latitude_Cent = (int)lati_cent_tmp;lati_second_tmp = (lati_cent_tmp - GPS->latitude_Cent) * 60;GPS->latitude_Second = (int)lati_second_tmp;GPS->longitude_Degree = (int)GPS->longitude / 100; //分离经度long_cent_tmp = (GPS->longitude -GPS->longitude_Degree * 100); GPS->longitude_Cent = (int)long_cent_tmp;long_second_tmp = (long_cent_tmp -GPS->longitude_Cent) * 60; GPS->longitude_Second = (int)long_second_tmp;speed_tmp = Get_Float_Number(&buf[GetComma(7, buf)]); //速度(单位:海里/时) GPS->speed = speed_tmp * 1.85; //1 海里=1.85 公里GPS->direction = Get_Float_Number(&buf[GetComma(8, buf)]); //角度GPS->D.hour = (buf[7] - '0') * 10 + (buf[8] - '0'); //时间GPS->D.minute = (buf[9] - '0') * 10 + (buf[10] - '0');GPS->D.second = (buf[11] - '0') * 10 + (buf[12] - '0');tmp = GetComma(9, buf);GPS->D.day = (buf[tmp + 0] - '0') * 10 + (buf[tmp + 1] - '0'); //日期GPS->D.month = (buf[tmp + 2] - '0') * 10 + (buf[tmp + 3] - '0');GPS->D.year = (buf[tmp + 4] - '0') * 10 + (buf[tmp + 5] - '0')+2000;UTC2BTC(&GPS->D);return 1;}}return 0;}intGPS_GGA_Parse(char *line,GPS_INFO *GPS) //全球定位数据,最大帧为72 { //丛这个数据得到海拔的数据ucharch, status;char *buf = line; ch = buf[4];status = buf[GetComma(2, buf)];if (ch == 'G') //$GPGGA 丛这个数据得到海拔的数据{ if (status != ','){GPS->height_sea = Get_Float_Number(&buf[GetComma(9, buf)]);GPS->height_ground = Get_Float_Number(&buf[GetComma(11, buf)]);return 1;}}return 0;}static float Str_To_Float(char *buf) //字符串到单精度的转换函数{ float rev = 0;float dat;int integer = 1;char *str = buf; //inti;while(*str != '\0'){ switch(*str){ case '0':dat = 0;break;case '1':dat = 1;break;case '2':dat = 2;break;case '3':dat = 3;break;case '4':dat = 4;break;case '5':dat = 5;break;case '6':dat = 6;break;case '7':dat = 7;break;case '8':dat = 8;break;case '9':dat = 9;break;case '.':dat = '.';break;}if(dat == '.'){ integer = 0;i = 1;str ++;continue;}if( integer == 1 ){rev = rev * 10 + dat;}else{ rev = rev + dat / (10 * i);i = i * 10 ;}str ++;}return rev;}static float Get_Float_Number(char *s){ char buf[10];uchari;float rev;i=GetComma(1, s);i = i - 1;strncpy(buf, s, i);buf[i] = 0;rev=Str_To_Float(buf);return rev;}static double Str_To_Double(char *buf) //字符串到双精度的转换函数{ double rev = 0;double dat;int integer = 1;char *str = buf;inti;while(*str != '\0'){ switch(*str) {case '0':dat = 0;break;case '1':dat = 1;break;case '2':dat = 2;break;case '3':dat = 3;break;case '4':dat = 4;break;case '5':dat = 5;break;case '6':dat = 6;break;case '7':dat = 7;break;case '8':dat = 8;break;case '9':dat = 9;break;case '.':dat = '.';break; }if(dat == '.'){integer = 0;i = 1;str ++;continue;}if( integer == 1 ){ rev = rev * 10 + dat;}else{rev = rev + dat / (10 * i);i = i * 10 ;}str ++;}return rev;}static double Get_Double_Number(char *s){ char buf[10];uchari;double rev;i=GetComma(1, s);i = i - 1;strncpy(buf, s, i);buf[i] = 0;rev=Str_To_Double(buf);return rev;}static ucharGetComma(ucharnum,char *str){ uchari,j = 0;intlen=strlen(str); //字符串的长度for(i = 0;i <len;i ++){ if(str[i] == ',') //计算字符串中的逗号的个数j++;if(j == num)return i + 1; //把逗号后的字符下标值返回}return 0;}static void UTC2BTC(DATE_TIME *GPS){ GPS->second ++;if(GPS->second > 59){ GPS->second = 0;GPS->minute ++;if(GPS->minute > 59){ GPS->minute = 0;GPS->hour ++;}}GPS->hour = GPS->hour + 8;if(GPS->hour > 23){ GPS->hour -= 24;GPS->day += 1;if(GPS->month == 2 ||GPS->month == 4 ||GPS->month == 6 ||GPS->month == 9 ||GPS->month == 11 ){ if(GPS->day > 30){ GPS->day = 1;GPS->month++;}}else{ if(GPS->day > 31){ GPS->day = 1;GPS->month ++;}}if(GPS->year % 4 == 0 ){ if(GPS->day > 29 && GPS->month == 2){ GPS->day = 1;GPS->month ++;}}else{ if(GPS->day > 28 &&GPS->month == 2){ GPS->day = 1;GPS->month ++;}}if(GPS->month > 12){ GPS->month -= 12;GPS->year ++;}}}void Int_To_Str(intx,char *Str){ int t;char *Ptr,Buf[5];inti = 0;Ptr = Str;if(x < 10) // 当整数小于10 时,转化为"0x"的格式{ *Ptr ++ = '0';*Ptr ++ = x+0x30;}else{ while(x > 0){t = x % 10;x = x / 10;Buf[i++] = t+0x30; // 通过计算把数字转化成ASCII 码形式}i -- ;for(;i>= 0;i --) // 将得到的字符串倒序{*(Ptr++) = Buf[i];}}*Ptr = '\0';}LCD 程序:#include "LCD.h"void delay(uint z) // 延时1MS{ uint x, y;for (x = z; x > 0; x--)for(y = 110; y > 0; y--);}void clr_screen(){ Lcd_WriteCmd(0x34); //扩充指令操作delay(5);Lcd_WriteCmd(0x30); //基本指令操作delay(5);Lcd_WriteCmd(0x01); //清屏delay(5);}void Lcd_WriteCmd(ucharcmd) //LCD 命令写入函数{LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;_nop_();_nop_();delay(5);P0 = cmd;DelayNOP();LCD_EN = 1;DelayNOP();LCD_EN = 0; ;}void Lcd_WriteDat(uchardat) //LCD 数据写入函数{LCD_RS = 1;LCD_RW = 0;LCD_EN = 0;P0 = dat;delay(5);DelayNOP();LCD_EN = 1;DelayNOP();LCD_EN = 0;}void Lcd_Init(void){ Lcd_WriteCmd(0x34); //扩充指令操作delay(5);Lcd_WriteCmd(0x30); //基本指令操作delay(5);Lcd_WriteCmd(0x0C); //显示开,关光标delay(5);Lcd_WriteCmd(0x01); //清除LCD 的显示内容delay(5);}void Lcd_SetPos(ucharX,uchar Y) //显示地址处理{ucharpos;if (X==0){X=0x80;}else if (X==1){X=0x90;}else if (X==2){X=0x88;}else if (X==3){X=0x98;}pos = X+Y ;Lcd_WriteCmd(pos); //显示地址}void Lcd_DispLine(uchar line, ucharpos, uchar *str){inti = 0;Lcd_SetPos(line, pos); //LCD 显示位置设定while (str[i] != '\0'){ Lcd_WriteDat(str[i]); //LCD 显示数据i++;}}源程序:#include <reg51.h>#include <stdio.h>#include <string.h>#include "GPS.h"#include "LCD.h"#include "display.h"sbit led1 = P2^0; //接收数据指示灯sbit led2 = P2^1; //GPRMC 数据有效指示灯sbit led3 = P2^2; //GPGGA 数据有效指示灯#define REV_YES led1 = 0#define REV_NO led1 = 1#define RMC_YES led2 = 0#define RMC_NO led2 = 1#define GGA_YES led3 = 0#define GGA_NO led3 = 1char xdatarev_buf[80]; //接收缓存ucharxdatarev_start = 0; //接收开始标志ucharxdatarev_stop = 0; //接收停止标志ucharxdatagps_flag = 0; //GPS 处理标志ucharxdatachange_page = 0; //换页显示标志ucharxdatanum = 0; //extern GPS_INFO GPS; //在display.c 中定义,使用时要加extern/*****************************//********初始化串口***********//******************************/void Uart_Init(void){TMOD = 0x21; //0010 0001 定时器1 工作在模式2(8 位自动重装)//定时器0 工作在模式1(16 位定时器/计数器)//SCON=0X50;PCON=0X00;TH0=0x3c;TL0=0xb0;TH1=0xFa; // 波特率为4800TL1=0xFa; //TR1=1; //开启定时器1REN=1; //允许接收数据SM0=0; //串口工作在第一模式SM1=1;TI=0; //发送中断清0RI=0; //接收中断清0EA=1; //开总中断ES=1; //串口1 中断允许ET0 = 1; //定时器0 中断允许}/****************************************主函数/****************************************/void main(void){ ucharerror_num = 0;Uart_Init(); //初始化串口Lcd_Init(); //初始化LCDGPS_Init(); //初始化GPSrev_stop=0; //接收停止标志REV_NO; //接收数据指示灯关while(1){if (rev_stop) //如果接收完一行{TR0 = 1; //开启定时器0REV_YES; //接收数据指示灯开if ( change_page % 2 == 1) //换页{if (GPS_GGA_Parse(rev_buf, &GPS)) //解析GPGGA{GGA_YES;GPS_DisplayTwo(); //显示第二页信息error_num = 0;gps_flag = 0; //GPS 处理标志rev_stop = 0; //接收停止标志REV_NO; //接收数据指示灯关}else{error_num++;if (error_num>= 20) //如果数据无效超过20 次{GGA_NO; //GPGGA 数据无效指示灯error_num = 20;GPS_Init(); //返回初始化}gps_flag = 0;rev_stop = 0;REV_NO;}}else{if (GPS_RMC_Parse(rev_buf, &GPS)) //解析GPRMC{RMC_YES;GPS_DisplayOne(); //显示GPS 第一页信息error_num = 0;gps_flag = 0;rev_stop = 0;REV_NO;}else{error_num++;if (error_num>= 20) //如果数据无效超过20 次{RMC_NO;error_num = 20;GPS_Init(); //返回初始化}gps_flag = 0;rev_stop = 0;REV_NO;}}}}}/***************************************************************//*************************定时器0 用作换页***********************/ /***************************************************************/void timer0(void) interrupt 1{ static uchar count = 0;TH0 = 0x3c;TL0 = 0xb0;if (count == 200) //2*5 秒钟{count = 0;change_page++; //换页if (change_page == 10)change_page=0;}}/***************************************************************//*************************串口数据接收**************************//***************************************************************/ void Uart_Receive(void) interrupt 4{ucharch;ES = 0; //串口1 中断禁止if (RI) //如果接收完成则进入{ch = SBUF;if ((ch == '$') && (gps_flag == 0)) //如果收到字符'$',便开始接收{rev_start = 1;rev_stop = 0; //接收停止标志}if (rev_start == 1) //标志位为1,开始接收{rev_buf[num++] = ch; //字符存到数组中if (ch == '\n') //如果接收到换行{rev_buf[num] = '\0';rev_start = 0;rev_stop = 1; //接收停止标志gps_flag = 1;num = 0;}}}RI = 0; //RI 清0,重新接收ES = 1; //串口1 中断允许}。
// c51红外解码、超声波测距程序#include <reg52.h>#define uchar unsigned char#define uint unsigned int#define count 4uchar data IRcode[4]; //定义一个4字节的数组用来存储代码uchar table[4];uchar enled[4]={0x1f,0x2f,0x4f,0x8f};uchar CodeTemp,temp,tt; //编码字节缓存变量uchari,j,k,temp,timeH,timeL,succeed_flag,flag,h,h1,h2,a,key,key1,key2; //延时用的循环变量uint distance,distance1,time; //距离,timesbit IRsignal=P3^2; //HS0038接收头OUT端直接连P3.2(INT0)sbit come=P3^3;sbit d=P1^1;//发送码sbit BZ=P1^0;sbit s=P3^7;//38ksbit ss=P3^6;//38kuchar m;// 开关控制//sbit n=P2;//电机反转code unsigned charseg7code[10]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28}; //显示段码/**************************** 定时器0中断************************/void timer0() interrupt 1{TH0=(65536-count)/256;TL0=(65536-count)%256;s=~s;//产生38K信号ss=~ss;//tt++;//发送超声波个数}/**************************** 延时0.9ms子程序************************/void Delay0_9ms(void){uchar j,k;for(j=18;j>0;j--)for(k=20;k>0;k--);}/***************************延时1ms子程序**********************/void Delay1ms(void){uchar i,j;for(i=2;i>0;i--)for(j=230;j>0;j--);}/***************************延时4.5ms子程序**********************/ void Delay4_5ms(void){uchar i,j;for(i=10;i>0;i--)for(j=225;j>0;j--);}/**************************** 解码延时子程序************************/ void Delay(void){uchar i,j,k;for(i=100;i>0;i--)for(j=100;j>0;j--)for(k=3;k>0;k--);}/**************************** 显示延时子程序************************/ void ledDelay(unsigned int tc) //延时程序{unsigned int i,j;for(i=0;i<10;i++)for(j=0;j<tc;j++);}/************************************************ ****************///定时器1中断,用做超声波测距无回波void timer1() interrupt 3{TR1=0;ET1=0;EX1=0;TH1=0;TL1=0;}/***********************显示程序*********************/ void Led(int date) //显示函数{ int i;table[0]=date/1000;table[1]=date/100%10;table[2]=date/10%10;table[3]=date%10;date=0;for(i=0;i<120;i++){P2=enled[i%4]&m;//P2口高四位控制数码管,低位陪分控制继电器P0=seg7code[table[i%4]]; //取出千位数,查表,输出。
C51程序在Keil C51下的调试步骤现在广泛使用的C51集成开发环境是Keil软件。
要使用Keil软件,首先要正确安装Keil软件,该软件的Eval版本可以直接去http://www. 下载,其步骤与一般Windows 程序安装类似,这里就不再赘述了。
Keil软件的详细说明见相关资料,这里仅作简要说明,以便于读者在后面的章节中实际动手调试、仿真程序。
1.建立工作项目文件图1启动Keil μVison2启动Keil μVison2,如果打开后就有打开的文件,单击“Project->Close Project”菜单将其关闭。
单击“File->New... ",打开一个新的文件输入窗口,在这个窗口里输入上述源程序。
输入完毕之后,选择“File-->Save",给这个文件取名保存,取名字的时候必须要加上扩展名,一般C语言程序均以“.c”为扩展名(一定要加扩展名,否则后面添加文件就找不到该文件,这是初学者很容易忘记的),这里将其命名为mytest.c。
图2 建立工程文件单击“Project->New Project...",出现对话框,要求给将要建立的工程起一个名字,这里起名为test,不需要输入扩展名。
单击“保存”按钮,出现第二个对话框,如图3所示:图3 CPU选择窗口这个对话框要求选择工程中所用的单片机型号,这里选择Atmel公司的89S52芯片。
单击ATMEL前面的“+”号,展开该层,单击其中的89S52,然后再单击“确定”按钮,会出现一个对话框,询问是否要将标准的8052启动代码加入工程,单击“是”按钮。
此时,在工程窗口的文件页中出现了“Target 1”,前面有“+”号,单击“+”号展开,可以看到下一层的“Source Group 1 ",需要手动把刚才编写好的源程序加入,方法如下:单击“Source Group 1 ",使其反白显示,然后单击鼠标右键,出现一个下拉菜单,如图4所示。
单片机c51程序设计单片机C51程序设计是一门结合了硬件知识和软件编程技能的学科,它广泛应用于自动化控制、智能设备、嵌入式系统等领域。
C51单片机是指使用C语言进行编程的8051系列单片机,它具备丰富的指令集和灵活的编程方式。
下面将从单片机的基本概念、C51编程基础、程序设计步骤以及实例分析等方面进行介绍。
单片机的基本概念单片机,又称微控制器,是一种集成了处理器核心、存储器、输入/输出接口等的微型计算机系统。
它具有体积小、功耗低、成本低、可靠性高等特点。
C51单片机是基于Intel 8051微控制器架构的,具有8位数据总线和16位地址总线,支持多种外设接口。
C51编程基础1. C语言基础:熟悉C语言的基本语法,如变量声明、条件语句、循环语句、函数等。
2. 数据类型:了解C51单片机支持的数据类型,包括特有寄存器位操作。
3. 内存结构:掌握C51单片机的内存结构,包括内部RAM、外部RAM、程序存储器等。
4. 中断系统:理解中断的概念和中断服务程序的编写。
5. 定时器/计数器:了解如何使用单片机的定时器/计数器进行时间控制和事件计数。
程序设计步骤1. 需求分析:明确程序设计的目标和功能需求。
2. 系统设计:设计系统的整体架构,包括硬件连接和软件模块划分。
3. 编写代码:根据设计编写C51程序代码,包括初始化代码、主函数、中断服务程序等。
4. 调试:使用仿真软件或实际硬件对程序进行调试,确保程序正确运行。
5. 优化:根据调试结果对程序进行优化,提高效率和稳定性。
6. 测试:进行全面的测试,确保程序在各种条件下都能稳定运行。
实例分析以一个简单的LED闪烁程序为例,介绍C51程序设计的基本流程:```c#include <reg51.h>// 定义LED连接的端口#define LED_PORT P1void delay(unsigned int ms) {unsigned int i, j;for (i = ms; i > 0; i--)for (j = 110; j > 0; j--);}void main() {while (1) {LED_PORT = 0xFF; // 关闭所有LED灯delay(500); // 延时500msLED_PORT = 0x00; // 打开所有LED灯delay(500); // 延时500ms}}```在这个例子中,我们首先包含了8051单片机的寄存器定义文件`reg51.h`,定义了LED灯连接的端口为P1。
这其中包括1602驱动头文件,和解析主程序,使用时分开粘贴到对应的文件中/*LCD1602驱动,兼容LCD2402*/sbit LCD_DB0= P0^0;sbit LCD_DB1= P0^1;sbit LCD_DB2= P0^2;sbit LCD_DB3= P0^3;sbit LCD_DB4= P0^4;sbit LCD_DB5= P0^5;sbit LCD_DB6= P0^6;sbit LCD_DB7= P0^7;sbit LCD1602_RS=P2^4;sbit LCD1602_RW=P2^5;sbit LCD1602_EN=P2^6;void LCD_write_char( unsigned x,unsigned char y,unsigned char dat); 0f0f8F0c0c0c,'0'};");LCD_write_string(0,1,"Please Check..");while(buf_full==0);LCD_cls();dsp_count=0;}}else{ ;for(i=3;i<10;i++){LCD_write_char(i+2,0,JD[i]);}LCD_write_char(0,1,WD_a); ;for(i=2;i<9;i++){LCD_write_char(i+3,1,WD[i]);}}LCD_write_char(14,1,use_sat[0]); ;for(i=3;i<10;i++){LCD_write_char(i+2,0,JD[i]);}LCD_write_char(0,1,WD_a); ;for(i=2;i<9;i++){LCD_write_char(i+3,1,WD[i]);}}LCD_write_char(14,0,use_sat[0]);dot_count++;elsebreak ;}switch(dot_count){case 1:b=((speed[0]-'0')*10+(speed[2]-'0'))*;break;case 2:b=((speed[0]-'0')*100+(speed[1]-'0')*10+(speed[4]-'0'))*;break;case 3:b=((speed[0]-'0')*1000+(speed[1]-'0')*100+(speed[2]-'0')*10+(speed[4]-'0'))*;break;}if(b>maxspeed){maxspeed=b;}/*************************************最大速度处理*************************************/if(count<10){for(i=0;i<5;i++){LCD_write_char(i,0,speed[i]);;hspeed[4]= maxspeed%10+0x30;count++;LCD_write_string(5,0,"Km/h A");LCD_write_char(0,0,hspeed[0]);LCD_write_char(1,0,hspeed[1]);LCD_write_char(2,0,hspeed[2]);LCD_write_char(3,0,hspeed[3]);LCD_write_char(4,0,hspeed[4]); //最大速度显 */}/*******************************************************************************/for(i=0;i<5;i++){LCD_write_char(11+i,0,angle[i]);}}buf_full&=~0x04;dsp_count=0;}}}}}bit chk_key(void){if(!KEY1){delayms(10);if(!KEY1){while(!KEY1);delayms(10);return(1);}}LCD_cls(); //清屏return(0);}//系统初始化void sys_init() {unsigned char i;SCON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */TMOD = 0x21; /* TMOD: timer 1, mode 2, 8-bit reload */if(GPS_SPD){TH1 = 0xfa; /* TH1: reload value for 9600 baud @ */ }else{TH1 = 0xfd; /* TH1: reload value for 4800 baud @ */ }TR1 = 1; /* TR1: timer 1 run */LCD_init(8); //初始化LCDLCD_write_string(0,0," GPS SIRF II 2 ");LCD_write_string(0,1," 11-11-23 1342 ");for(i=1;i<4;i++){delayms(250);}//LCD_cls();IE=0x90; //开总中断、串口中断}//串口接收中断void uart(void) interrupt 4{unsigned char tmp;if(RI){tmp=SBUF;switch(tmp){case '$':cmd_number=0; //命令类型清空mode=1; //接收命令模式byte_count=0; //接收位数清空break;case ',':seg_count++; //逗号计数加1byte_count=0;break;case '*':switch(cmd_number){case 1:buf_full|=0x01;break;case 2:buf_full|=0x02;break;case 3:buf_full|=0x04;break;}mode=0;break;default:if(mode==1){//命令种类判断cmd[byte_count]=tmp; //接收字符放入类型缓存if(byte_count>=4){ //如果类型数据接收完毕,判断类型if(cmd[0]=='G'){if(cmd[1]=='P'){if(cmd[2]=='G'){if(cmd[3]=='G'){if(cmd[4]=='A'){cmd_number=1;mode=2;seg_count=0;byte_count=0;}}else if(cmd[3]=='S'){if(cmd[4]=='V'){cmd_number=2;mode=2;seg_count=0;byte_count=0;}}}else if(cmd[2]=='R'){if(cmd[3]=='M'){if(cmd[4]=='C'){cmd_number=3;mode=2;seg_count=0;byte_count=0;}}}}}}}else if(mode==2){//接收数据处理switch (cmd_number){case 1: //类型1数据接收。