📄 main.c
字号:
//多模块程序编写得I2C程序!!
//实现简单的数字时钟---DS1307
//experience
//判断时刻,读取时钟为bcd码,十六进制
//先存起步价,无一个误差脉冲(100m),否则先判断则有100m误差(一个脉冲)
//比较分段里程,不用公里,而直接比较100m,还可以减少一个除法
//按键切换的问题,标志位在中断服务程序取反!!!!!!!可悲!!!-----------------------
//整个单片机执行时序问题?----计算等待费用时候!!----------------------
//串口问题!!一定是定时器2出现问题 !!!!
//串行口关于两个文件变量定义的问题!!
//IDATA为什么不会抱错呢
//养成良好的编程习惯!!内存分配-----------
#include<reg52.h>
#include<intrins.h>
#include<serial.h>
#include<lcd.h>
#include<IIC.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
unsigned char idata buf_seri[6];
bit ack_seri;
uchar code table1[16]=" MARTIAN STUDIO ";
uchar code table2[16]="状态:载客 ";
uchar code table3[16]="状态:空车 ";
//声明全局变量
uchar *s ; //I2C器件读写单元缓冲区首地址指针
uchar no; //读写I2C器件字节数
uchar sla ; //I2C器件内部地址,都为写地址
uchar suba; //器件内部地址
uchar bdata flag ; //位寻址区定义
uchar bcd_num ;
sbit fg_1s =flag^4; //1s刷新标志
sbit fg_1s1=flag^5; //1s刷新,计算等待费用
sbit fg_qibu =flag^7;
bit fg_day_ng;
bit fg_100 ;
bit fg_wait;
bit key_fg;
bit fg_on;
bit fg_seri;
uchar buf_key ; //存按键值
uchar idata time_temp[4] ; //存实时读取1307系统时间
uchar idata date_temp[3] ; //存实时读取1307系统时间
uchar idata lcd_temp[16] ; //显示缓冲? uchar idata dis_temp[8];
uchar idata mrd[8] ; //接收缓冲区
uchar idata trd[8] ; //发送缓冲区
// uchar idata table_shape0[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//字形表0-9
// uchar idata table_shape1[10]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};//字形表
uchar idata table_time[7]={0x00,0x00,0x06,0x03,0x08,0x09,0x05};//设置起始时间2005年9月8号8点0分0秒
uchar buf_sec;
uchar idata stack[10] ; //人工栈
uchar idata buf_bcd[9] ; //存放hex to bcd 后的 bcd 最多存放8位
ulong buf_dis ; //存放里程,四个字节
ulong buf_pre ; //存放价格,四个字节
ulong pre_dis ; //存放上次载客里程
ulong pre_pre ; //存放上次载客费用
ulong total_pre; //存放总营业额
ulong day_pre ; //日额
uint qibu_day ; //存白天起步价格,10元转1000
uint qibu_ng ; //存夜间起步价格,12元转1200
uint midd_day ; //存3-8km价格1.6元转16
uint huikong_day ; //存>8km价格2.2元转22
uint wait_day ; //等待价格,1.5元转150
ulong wait_sec ; //存等待时间,为精确计算,按照秒算
uint wait_min ; //存等待分
uint wait_second ; //存等待秒
uchar dis_wmin ; //载客结束显示等待分钟
uchar dis_wsec ; //载客结束显示等待秒
uchar dec_sec ; //存20,1s刷新
uchar dia ; //存放直径
uchar buf_dia ; //计算速度,定时次数
uchar extra ; //加价
uint buf_sp ; //存放速度
uint buf_sp_temp;
uchar pu ; //存脉冲数191----计算里程
uchar buf_pu ; //暂存脉冲数191
uchar error_type _at_ 0x30 ; //存放写器件错误代码类型,全局变量
//初始化清零子函数
void clr_ram( uchar * s,uchar no )
{ static uchar i;
for(i=0;i<no;i++)
s[i]=0;
}
//清除LCD
void clr_lcd( uchar *s,uchar no)
{ static uchar i;
for(i=0;i<no;i++)
s[i]=0x20;
}
//hex 转 bcd 子程序
//入口参数长整型数据
//出口参数存bcd码缓冲区
void hextobcd(ulong a ,uchar * s)
{
static uchar i;
ulong temp=a;
for(i=0; temp;i++ )
{ s[i]=temp%10;
temp/=10;
}
s[i]='\0';
bcd_num=i;
}
void out_put( uint a)
{
static idata uchar b[6]; //存bcd码
static idata uchar c[6]; //指针
static uchar j,i;
hextobcd(a,b);
//倒转
i=bcd_num;
for(j=0;j<i; j++)
c[j]=b[i-j-1]+0x30;
for(j=0;j<i;j++)
b[j]=c[j];
b[j]='\0'; //结束标志
UartSendString(b); //UartSendString(c);错误,指针已经被改变
}
//初始化函数
void init(void)
{ clr_ram(time_temp,4) ; //时间存放单元清零
clr_ram(date_temp,3) ; //日期存放单元清零
clr_ram(dis_temp,8) ; //显示缓冲区清零
clr_ram(trd,8) ; //发送缓冲区单元清零
clr_ram(mrd,8) ; //接收缓冲区单元清零
clr_ram(buf_bcd,9) ; //bcd码缓冲区清零
clr_ram(stack,10) ; //清除人工栈
//以下单元清零
fg_1s =0; //显示刷新1s未到
fg_1s1=0; //计算等待费用1s未到
fg_wait=0;
key_fg=0;
fg_on=0;
fg_100=0;
fg_qibu=1; //计算起步价
fg_day_ng=1; //day
buf_sp=0;
buf_sp_temp=0;
wait_sec=0;
wait_min=0;
buf_sp=0;
dec_sec=20;
buf_key=0; //清除按键值
buf_dis=0;
buf_pre=0;
pre_dis=0;
pre_pre=0;
total_pre=0;
day_pre=0;
buf_sec=table_time[0];
//以下参数可通过与PC机通信
dia=50; //存直径
extra=12; //夜间加价0.2
qibu_day=10000; //起步价格10
midd_day=160; //中间价格1.6元/km
huikong_day=210; //回空价格2.2元/km
wait_day=1500; //等待价格1.5元/min
pu=buf_pu=191; //计算里程,脉冲数
buf_dia=dia;
qibu_ng= qibu_day/10*extra;//起步价格12
//定时器设置
TMOD=0X21; //设置TO工作方式
TH0=0X6c; //设置T0计数初值 65536-37680=0x6cd0;
TL0=0Xd0;
ET0=1; //启动定时中断
ET1=0;
//中断设置
IE0=0 ;
IE1=0 ;
IT0=1 ;
IT1=1 ;
EX0=1 ;
EX1=1 ;
EA=1 ;
TR0=1; //启动定时器
TR1=1;
}
//设置时间
void set_time(void)
{
no=7; //写入1307七个字节
suba=0X00; //器内地址
sla=0XD0; //器件地址
if ( ! ISendStr(sla,suba,table_time,no) )
error_type=0x01; //写时钟错误,代码0x01
}
//读取1307系统时间,入口参数为指向字节单元的指针,
//返回1表示读取成功,读取内容存指针所指缓冲区
void rd_time_date(uchar *p_time, uchar *p_date )
{ //读时间
no=4; //读取1307七个字节
suba=0X00; //器内地址
sla=0XD0; //器件地址
if ( ! IRcvStr(sla,suba, p_time, no) )
error_type=0x02; //读时钟错误,代码0x02
//读日期
no=3; //读取1307七个字节
suba=0X04; //器内地址
sla=0XD0; //器件地址
if ( ! IRcvStr(sla,suba, p_date, no) )
error_type=0x02; //读时钟错误,代码0x02
}
//车行驶,切换按键,不影响车里程和费用计算
void on_taxi(void)
{
//根据100m脉冲加1,代表100m ,根据价格计算费用
if ( fg_100 )
{ buf_dis+=1; //里程加100m
fg_100=0; //清标志
//price
if ( buf_dis<=30 ) buf_pre=buf_pre;
if( buf_dis>30 && buf_dis<=80 && fg_day_ng ) buf_pre+=midd_day ;
if( buf_dis>30 && buf_dis<=80 && !fg_day_ng ) buf_pre=buf_pre+midd_day/10*extra;
if( buf_dis>80 && fg_day_ng ) buf_pre+=huikong_day;
if( buf_dis>80 && !fg_day_ng ) buf_pre+=(huikong_day/10*extra);
}
//等待费用
if ( buf_sp<=5 && fg_1s1 )
{
wait_sec+=1; //等待累加1s
dis_wmin=wait_min= wait_sec/60;
dis_wsec=wait_second=wait_sec%60;
}
//解决了问题,终于发现问题了!!
if ( wait_min >5 && wait_second==0 &&fg_1s1 )
fg_wait=1; //类似中断处理内设置标志位
if ( fg_wait )
{ fg_wait=0;
if ( fg_day_ng )
buf_pre+=wait_day;
else
buf_pre=buf_pre+(wait_day/10*extra);
}
fg_1s1=0;
}
//key10----service
//开始载客
//计算里程和费用(里程费用和等待费用)
void up_taxi(void)
{
fg_on=1;
if ( time_temp[2]<=0x22 && time_temp[2] >=0x6 )
fg_day_ng=1;
else fg_day_ng=0;
//判断起步价格
if(fg_qibu)
if ( fg_day_ng )
buf_pre=qibu_day;
else
buf_pre=qibu_ng;
fg_qibu=0;
clr_ram(buf_bcd,8); //清除bcd缓冲区单元
hextobcd(buf_dis,buf_bcd); //转化距离为bcd
//显示里程
//显示里程
lcd_temp[0]=0xc0;
lcd_temp[1]=0xef;
lcd_temp[2]=0xb3;
lcd_temp[3]=0xcc;
lcd_temp[4]=0xa3;//显示冒号
lcd_temp[5]=0xba;
if ( buf_bcd[3] )
lcd_temp[6]=buf_bcd[3]+0x30;
else lcd_temp[6]=0x20;
if ( buf_bcd[3]==0 && buf_bcd[2]==0 )
lcd_temp[7]=0x20;
else lcd_temp[7]=buf_bcd[2]+0x30;
lcd_temp[8]=buf_bcd[1]+0x30;
lcd_temp[9]=0x2e; //点
lcd_temp[10]=buf_bcd[0]+0x30;
//KM
lcd_temp[11]=0x4B;
lcd_temp[12]=0x4D;
lcd_dis_mul(16,0x88,lcd_temp);
clr_lcd(lcd_temp,16);
clr_ram(buf_bcd,8); //清除bcd缓冲区单元
hextobcd(buf_pre,buf_bcd); //转为费用为bcd
//显示费用
lcd_temp[0]=0xb7;
lcd_temp[1]=0xd1;
lcd_temp[2]=0xd3;
lcd_temp[3]=0xc3;
lcd_temp[4]=0xa3;//显示冒号
lcd_temp[5]=0xba;
if ( buf_bcd[5] )
lcd_temp[6]=buf_bcd[5]+0x30;
else lcd_temp[6]=0x20;
if ( buf_bcd[5]==0 && buf_bcd[4]==0 )
lcd_temp[7]=0x20;
else lcd_temp[7]=buf_bcd[4]+0x30;
lcd_temp[8]=buf_bcd[3]+0x30;
lcd_temp[9]=0x2e; //点
lcd_temp[10]=buf_bcd[2]+0x30;
//显示元
lcd_temp[11]=0x59;
lcd_temp[12]=0x00;
lcd_dis_mul(16,0x90,lcd_temp);
clr_lcd(lcd_temp,16);
//根据100m脉冲加1,代表100m ,根据价格计算费用
if ( fg_100 )
{ buf_dis+=1; //里程加100m
fg_100=0; //清标志
//price
if ( buf_dis<=30 ) buf_pre=buf_pre;
if( buf_dis>30 && buf_dis<=80 && fg_day_ng ) buf_pre+=midd_day ;
if( buf_dis>30 && buf_dis<=80 && !fg_day_ng ) buf_pre=buf_pre+midd_day/10*extra;
if( buf_dis>80 && fg_day_ng ) buf_pre+=huikong_day;
if( buf_dis>80 && !fg_day_ng ) buf_pre+=(huikong_day/10*extra);
}
//等待费用
if ( buf_sp<=5 && fg_1s1 )
{
wait_sec+=1; //等待累加1s
dis_wmin=wait_min= wait_sec/60;
dis_wsec=wait_second=wait_sec%60;
}
//解决了问题,终于发现问题了!!
if ( wait_min >5 && wait_second==0 &&fg_1s1 )
fg_wait=1; //类似中断处理内设置标志位
if ( fg_wait )
{ fg_wait=0;
if ( fg_day_ng )
buf_pre+=wait_day;
else
buf_pre=buf_pre+(wait_day/10*extra);
}
fg_1s1=0;
}
//key1-1--service
//将时间存显示缓冲区单元
void dis_time( void )
{
static uchar temp;
lcd_temp[0]=0xca; //汉字
lcd_temp[1]=0xb1;
lcd_temp[2]=0xbc;
lcd_temp[3]=0xe4;
lcd_temp[4]=0xa3;
lcd_temp[5]=0xba;
temp=time_temp[2] ; //小时
temp>>=4 ; //循环右移四位
temp&=0x0f ; //取高四位
lcd_temp[6]=temp+0x30;
temp=time_temp[2] ;
temp&=0x0f ; //取高四?
lcd_temp[7]=temp+0x30;
lcd_temp[8]=0xa3; //冒号
lcd_temp[9]=0xba;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -