标题:
看不懂这个单片机程序的中断和计数初值
[打印本页]
作者:
heicad
时间:
2016-3-11 22:20
标题:
看不懂这个单片机程序的中断和计数初值
本帖最后由 heicad 于 2016-3-11 22:22 编辑
下面是一个51单片机的程序:中断和计数初值这看不懂
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uint num=0; //外部中断次数
uchar num1=0;
uint Speed_dat=0;
uint Total_Dis=0;
uchar Beep_speed=40;
sbit KEY1=P3^5;
sbit KEY2=P3^6;
sbit KEY3=P3^7;
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
#include"LCD1602.H"
#include"AT24C02.H"
void keyscan()
{
if(!KEY1)
{
delayms(5);
if(!KEY1)
{
if(Beep_speed<255)
Beep_speed++;
while(!KEY1);
}
}
else if(!KEY2)
{
delayms(5);
if(!KEY2)
{
if(Beep_speed>0)
Beep_speed--;
while(!KEY2);
}
}
else if(!KEY3)
{
delayms(5);
if(!KEY3)
{
Write_AT24C02_Byte(0,0);
Write_AT24C02_Byte(1,0);
Total_Dis=0;
dis_Mileage();
while(!KEY3);
}
}
}
void main()
{
uchar dat=0;
float M_dat=0.0;
init_1602();
Init_AT24C02();
dat=Read_AT24C02_Random(0);
Total_Dis=dat*256+Read_AT24C02_Random(1);
dis_Mileage();
TMOD=0X01;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
ET0=1;
TR0=1;
IT0=1; //边沿触发中断
EX0=1;
EA=1;
while(1)
{
if(num1>99)
{
num1=0;
M_dat+=(float)(Cur_Speed/3.60); //每0.1s走的米数
}
if(M_dat>1000.0) //路程每增加100m储存一次
{
M_dat-=1000.0;
Total_Dis+=1;
Write_AT24C02_Byte(0,Total_Dis/256);
Write_AT24C02_Byte(1,Total_Dis%256);
dis_Mileage();
}
display();
keyscan();
}
}
void T0_time() interrupt 1 //定时器0
{
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
if(num<500)
num++;
else
Speed_dat=0;
if(num1<100)
num1++;
}
void ex_0() interrupt 0 //外部中断0
{
Speed_dat=(500/num);
num=0;
}
#define uchar unsigned char
#define uint unsigned int
sbit EN=P2^7;
sbit RS=P2^5;
sbit RW=P2^6;
sbit BEEP=P2^0;
sbit LED1=P1^2;
sbit LED2=P1^3;
uchar LCD1602_Table[]="0123456789";
//LCD1602显示标尺 //0123456789abcdef
uchar code DIS_TAB1[]={" Speed:---Km/h "};
uchar code DIS_TAB2[]={"M: Km---Km/h"};
uint sum_dat=0;
uchar Cur_Speed=0;
extern uint Speed_dat;
extern uint Total_Dis;
extern void delayms(uint xms);
void WRITE_LCD1602_DAT(uchar date)
{
EN=0;
RS=1;
P0=date;
EN=0;
delayms(5);
EN=1;
}
void WRITE_LCD1602_COM(uchar date)
{
EN=0;
RS=0;
P0=date;
EN=0;
delayms(5);
EN=1;
}
void init_1602()
{
unsigned char i;
RW=0;
WRITE_LCD1602_COM(0x38);
WRITE_LCD1602_COM(0x0c);
WRITE_LCD1602_COM(0x06);
WRITE_LCD1602_COM(0x01);
WRITE_LCD1602_COM(0x80);
for(i=0;i<16;i++)
WRITE_LCD1602_DAT(DIS_TAB1[i]);
WRITE_LCD1602_COM(0x80+0x40);
for(i=0;i<16;i++)
WRITE_LCD1602_DAT(DIS_TAB2[i]);
}
void display()
{
static uint dat=0;
static uchar i=0;
if(i<6)
{
i++;
sum_dat+=Speed_dat;
}
else
{
i=0;
dat=sum_dat/10;
sum_dat=0;
}
Cur_Speed=dat;
WRITE_LCD1602_COM(0x80+7);
if(dat/100>0)
WRITE_LCD1602_DAT(LCD1602_Table[dat%1000/100]);
else
WRITE_LCD1602_DAT(' ');
if(dat/10>0)
WRITE_LCD1602_DAT(LCD1602_Table[dat%100/10]);
else
WRITE_LCD1602_DAT(' ');
WRITE_LCD1602_DAT(LCD1602_Table[dat%10]);
WRITE_LCD1602_COM(0x80+9+0x40);
if(Beep_speed/100>0)
WRITE_LCD1602_DAT(LCD1602_Table[Beep_speed%1000/100]);
else
WRITE_LCD1602_DAT(' ');
if(Beep_speed/10>0)
WRITE_LCD1602_DAT(LCD1602_Table[Beep_speed%100/10]);
else
WRITE_LCD1602_DAT(' ');
WRITE_LCD1602_DAT(LCD1602_Table[Beep_speed%10]);
if(dat>Beep_speed)
{
if(i<3)
BEEP=0;
else
BEEP=1;
LED1=0;
LED2=1;
}
else
{
BEEP=1;
LED1=1;
LED2=0;
}
}
void dis_Mileage()
{
WRITE_LCD1602_COM(0x80+0x40+2);
if(Total_Dis/1000>0)
WRITE_LCD1602_DAT(LCD1602_Table[Total_Dis%10000/1000]);
else
WRITE_LCD1602_DAT(' ');
if(Total_Dis/100>0)
WRITE_LCD1602_DAT(LCD1602_Table[Total_Dis%1000/100]);
else
WRITE_LCD1602_DAT(' ');
WRITE_LCD1602_DAT(LCD1602_Table[Total_Dis%100/10]);
WRITE_LCD1602_DAT('.');
WRITE_LCD1602_DAT(LCD1602_Table[Total_Dis%10]);
}
#include<intrins.h>
#define AT24C02_OP_READ 0xa1 // AT24C02器件地址以及读取操作
#define AT24C02_OP_WRITE 0xa0 // AT24C02器件地址以及写入操作
//#define AT24C02_MAX_ADDR 0xff // AT24C02最大地址
//unsigned char code dis_code[]={0x7e,0xbd,0xdb,0x7e,0xdb,0xbd,0x7e,0xff};// 写入到AT24C02的数据串
sbit AT24C02_SDA=P1^1;
sbit AT24C02_SCL=P1^0;
//sbit AT24C02_WP=P3^3; //写保护 “=0”读写 “=1” 只读
/*****************延时子程序***********************/
void Delay_1ms(unsigned int xms)
{
unsigned int i,j;
for(i=xms;i>0;i--)
for(j=122;j>0;j--);
}
/*****************24C02初始化子程序***********************/
void Init_AT24C02()
{
AT24C02_SDA=1; //总线空闲时,因各设备都是集电极或漏极开路,上拉电阻使SDA和SCL线都保持高电平。
// AT24C02_WP=1;
AT24C02_SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
}
/*****************24C02起始信号子程序***********************/
void AT24C02_Start()
{
AT24C02_SDA=1;
_nop_();
_nop_();
AT24C02_SCL=1;
_nop_();
_nop_();
AT24C02_SDA=0;
_nop_();
_nop_();
_nop_();
_nop_();
AT24C02_SCL=0;
}
/*****************24C02停止信号子程序***********************/
void AT24C02_Stop()
{
AT24C02_SDA=0;
_nop_();
_nop_();
AT24C02_SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
AT24C02_SDA=1;
_nop_();
_nop_();
}
/*****************24C02应答子程序***********************/
void AT24C02_ACK()
{
AT24C02_SDA=1; // 读取应答
_nop_();
_nop_();
AT24C02_SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
while(AT24C02_SDA); //等待应答信号
AT24C02_SCL=0;
_nop_();
_nop_();
}
/*****************读出24C02数据子程序***********************/
unsigned char Read_AT24C02_DATA()
{
unsigned char i,read_data;
for(i=0;i<8;i++)
{
AT24C02_SCL=1;
_nop_();_nop_();_nop_();_nop_();
read_data<<=1; //从高位到底位
read_data|=(unsigned char)AT24C02_SDA;
AT24C02_SCL=0;
_nop_();_nop_();_nop_();_nop_();
}
return(read_data);
}
/*****************写入24C02数据子程序***********************/
void Write_AT24C02_DATA(unsigned char write_data)
{
unsigned char i;
for(i=0;i<8;i++) // 循环移入8个位
{
AT24C02_SDA=(bit)(write_data&0x80);
_nop_();
AT24C02_SCL=1;
_nop_();
_nop_();
AT24C02_SCL=0;
write_data<<=1;
}
}
/*****************字节写入24C02数据子程序***********************/
void Write_AT24C02_Byte(unsigned char addr, unsigned char write_data) // 在指定地址addr处写入数据write_data
{
AT24C02_Start(); //发起始命令
Write_AT24C02_DATA(AT24C02_OP_WRITE); //从机地址写命令
AT24C02_ACK();
Write_AT24C02_DATA(addr); //发送AT24C02的字节地址
AT24C02_ACK();
Write_AT24C02_DATA(write_data); //发送数据到被寻址的存储单元
AT24C02_ACK();
AT24C02_Stop(); //停止信号
Delay_1ms(10); //延时等待AT24C02内部数据的擦写
}
unsigned char Read_AT24C02_Current()
// 在当前地址读取
{
unsigned char read_data;
AT24C02_Start();
Write_AT24C02_DATA(AT24C02_OP_READ);
AT24C02_ACK();
read_data = Read_AT24C02_DATA();
AT24C02_Stop();
return read_data;
}
unsigned char Read_AT24C02_Random(unsigned char addr)
// 在指定地址读取
{
AT24C02_Start();
Write_AT24C02_DATA(AT24C02_OP_WRITE);
AT24C02_ACK();
Write_AT24C02_DATA(addr);
AT24C02_ACK();
return(Read_AT24C02_Current());
}
复制代码
作者:
heicad
时间:
2016-3-11 22:20
如果这个看不懂,你需要再继续从基础学起。
简单地说如果不给定时器设定初值,他就从0开始计数,如果给他一个初值,就从初值基础上计数,定时器计数满后,会产生中断。定时/计数器计数到0FFFFH(16进制)也就是65536计满,(65536-1000)意思是从64536开始计数,再加1000个机器周期,计数器满,产生中断。至于(65536-1000)/256,就是将256的倍数装进定时器的高位寄存器,(65536-1000)%256,就是将256的余数装进定时器的低位寄存器,因为51单片机是8位的,所以低位只能计数到255,再加1便产生进位。进到高8位中。如果你手工计算好以后,将倍数和余数分别赋值给TH、TL也是一样。
作者:
heicad
时间:
2016-3-11 22:21
简单地说如果不给定时器设定初值,他就从0开始计数,如果给他一个初值,就从初值基础上计数,定时器计数满后,会产生中断。定时/计数器计数到0FFFFH(16进制)也就是65536计满,(65536-1000)意思是从64536开始计数,再加1000个机器周期,计数器满,产生中断。至于(65536-1000)/256,就是将256的倍数装进定时器的高位寄存器,(65536-1000)%256,就是将256的余数装进定时器的低位寄存器,因为51单片机是8位的,所以低位只能计数到255,再加1便产生进位。进到高8位中。如果你手工计算好以后,将倍数和余数分别赋值给TH、TL也是一样。
作者:
heicad
时间:
2016-3-11 22:21
heicad 发表于 2016-3-11 22:20
如果这个看不懂,你需要再继续从基础学起。
简单地说如果不给定时器设定初值,他就从0开始计数,如果给 ...
那这个是测速,然后显示出速度与里程,但我看不出它的半径什么的设在哪里,能帮解释一下吗,中断那个我问了同学,了解了不少。
作者:
735993584@qq.co
时间:
2017-4-3 21:27
同学,你好啊,你看懂了没,求解释。跟你一样的问题
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1