找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6406|回复: 3
收起左侧

51单片机源程序C语言,有详细注释

[复制链接]
ID:22230 发表于 2010-3-15 10:49 | 显示全部楼层 |阅读模式

#include<reg51.h>
#include<absacc.h>
#define PD XBYTE[0xb003]   //8255控制口
#define PC XBYTE[0xb002]   //8255扩展C口
#define PB XBYTE[0xb001]   //8255扩展B口
#define PA XBYTE[0Xb000]   //8255扩展A口

#define  LCDD XBYTE[0xe000]   //LCD控制口
#define LCDRS XBYTE[0xe003]   //LCD读口
#define LCDRW XBYTE[0xe001]   //LCD写口

#define ADCIN XBYTE[0xd000]   //ADC0809地址

sbit SCL=P1^6;    //i2c总线SCL线
sbit SDA=P1^7;    //i2c总线SDA线
sbit P1_5=P1^5;    //上,下限报警
sbit SpeakerP12=P1^2;  //蜂鸣器

unsigned char zfc[]="0000000/00:00:00";    //年,月,日,星期,时,分,秒
unsigned char zfctemp[7];       //日期和时间缓冲区
unsigned char smgd[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};  //数码管段吗
unsigned char smgb[]={0x00,0x01,0x02,0x03,0x04,0x05};       //数码管位码
unsigned char sc,sb,sa;  //数码管个位c,十位b,百位a      
unsigned char x=0;
unsigned char y=0;
unsigned char m,n;    //m保存上限值,n保存下限值
unsigned char stopread1307=1;


void delay(unsigned int ms){   //可变延时
 while(ms--);
 }

void i2cinit(void){     //IIC总线初始化
 SCL=1;
 delay(10);
 SDA=1;
 delay(10);
 SCL=0;
 delay(10);
 SDA=0;
 delay(10);
 }
void i2cstart(void){   //开始信号
 SDA=1;
 delay(10);
 SCL=1;
 delay(10);
 SDA=0;
 delay(10);
 SCL=0;
 }
void i2cstop(void){     //停止信号
 SCL=0;
 SDA=0;
 delay(10);
 SCL=1;
 delay(10);
 SDA=1;
}

void i2cack(){   //IIC应答信号
 SDA=0;
 SCL=1;
 delay(10);
 SCL=0;
 SDA=1;
}

bit testack(void){     //应答检测
unsigned char errorbit=0;
 SDA=1;
 SCL=1;
 delay(10);
 errorbit=SDA;
 SCL=0;
 return(errorbit);
}

void i2csend(unsigned char i_data){     //IIC发送
unsigned char t;
for (t=0;t<8;t++){
 SDA=(bit)(i_data&0x80);      //强制类型转换
 SCL=1;
 delay(10);
 SCL=0;
 i_data=i_data<<1;
 }
}

unsigned char i2cread(void){    //读一个字节
unsigned char t;
unsigned char i_data=0;
for(t=0;t<=7;t++){
 SCL=1;
 i_data=i_data*2; 
 i_data=i_data|((unsigned char)(SDA));   //强制类型转换
 SCL=0;
 }
 return i_data;
}

writei2c(unsigned char writedeviceadderss,unsigned char romadderss,
        unsigned char i_data){    // 一个字节写入i2c
 stopread1307=0;
 i2cstart();
 i2csend(writedeviceadderss); //如果writedeviceadderss=0xa0是24C02地址,0xd0是1307的地址
 if (testack()==1) return 0;
 i2csend(romadderss);   //romadderss是 数据 的存放地址
 if (testack()==1) return 0;
 i2csend(i_data);    //i_data是要写的数据
 if (testack()==1) return 0;
 i2cstop();
 delay(10);
}

unsigned char readi2c(unsigned char writedeviceadderss,unsigned char readdeviceadderss,
       unsigned char romadderss){      // 从i2c读出一个字节
 unsigned char i_data;
  stopread1307=0;
 i2cstart();
 i2csend(writedeviceadderss); //如果writedeviceadderss=0xa0是24C02地址,0xd0是1307的地址
 if (testack()==1)return 0;
 i2csend(romadderss);
 if (testack()==1)return 0;        

 i2cstart();
 i2csend(readdeviceadderss);  //如果readdeviceadderss=0xa1是24C02地址,0xd1是1307的地址
 if (testack()==1)return 0;

 i_data=i2cread();
 i2cack();
 i2cstop();
 return i_data;
 
}

unsigned char readi2cbyte(unsigned char *idataaddress,unsigned char mdata,unsigned char writedeviceadderss,
     unsigned char readdeviceadderss,unsigned char romadderss){  //连续读多个字节
 i2cstart();
 i2csend(writedeviceadderss); //如果writedeviceadderss=0xa0是24C02地址,0xd0是1307的地址
 if (testack()==1)return 0;
 i2csend(romadderss);
 if (testack()==1)return 0;        

 i2cstart();
 i2csend(readdeviceadderss);  //如果readdeviceadderss=0xa1是24C02地址,0xd1是1307的地址
 if (testack()==1)return 0;

 while(mdata!=0){
  *idataaddress=i2cread();
  i2cack();
  idataaddress++;
  mdata--;
 }
 i2cstop();
 return idataaddress;
}

void up(void){        //加一 且灯ED1闪烁
EX0=0;
stopread1307=0;
PD=0x09;
PD=0x07;
delay(5000);
x++;
PD=0x06;
y=0x06;
stopread1307=1;
}

void down(void){      //减一  且灯ED2闪烁
EX0=0;
stopread1307=0;
PD=0x07;
PD=0x09;
delay(5000);
x--;
PD=0x08;
y=0x08;
stopread1307=1;
}

void ppromup(void){
 writei2c(0xa0,0x0C,x);
}

void ppromdown(void){
  writei2c(0xa0,0x23,x);
}

void pprom(void){
 EX0=0;
 stopread1307=0;
 if (y==0x06) ppromup();    // 如果LED1亮存储上限值
 if (y==0x08) ppromdown();     // 如果LED2亮存储下限值
}

unsigned char keyscan(void){
unsigned char key;
 while(1) 
 {
  if (PB!=0xff){
    delay(2924);
    if (PB!=0xff){
     key=PB;
     switch(key){
      case 0xfe : return 0x01 ;break;
      case 0xfd : return 0x02 ;break;
      case 0xfb : return 0x03 ;break;
      case 0xf7 : return 0x04 ;break;
      case 0xef : return 0x05 ;break;
      case 0xdf : return 0x06 ;break;
      case 0xbf : return 0x07 ;break;
      case 0x7f : return 0x08 ;break;
        default : return 0xff;
     }
    }
   }
  return 0xff; 
 }  
}

void Speaker(void) {
 SpeakerP12=0;
 delay(500);
 SpeakerP12=1;
 delay(500);
}

void ADCSTART(void) interrupt 0{
 x=ADCIN;
 ADCIN=0x00;    //通道0
 stopread1307=1; 
}

void LCDINIT(){
 delay(20000); 
 LCDD=0x38;
 delay(50);
 LCDD=0x0c;
 delay(50);
 LCDD=0x01;
 delay(10);
}

void readup(void){       //读上限
  EX0=0;
 stopread1307=0;
 x=readi2c(0xa0,0xa1,0x0C);
 m=x;
}

void readdown(void){      //读下限
 EX0=0;
 stopread1307=0;
 x=readi2c(0xa0,0xa1,0x23);
 n=x;
}

void read1307(){
 zfc[15]=(zfctemp[0]&0x0f)+0x30;    //秒个位
 zfc[14]=((zfctemp[0]>>4)&0x0f)+0x30;   //秒十位
 zfc[13]=':';
 zfc[12]=(zfctemp[1]&0x0f)+0x30;    //分个位
 zfc[11]=((zfctemp[1]>>4)&0x0f)+0x30;  //分十位
 zfc[10]=':';
 zfc[9]=(zfctemp[2]&0x0f)+0x30;    //时个位
 zfc[8]=((zfctemp[2]>>4)&0x0f)+0x30;   //时十位
 zfc[7]='/';            //星期
 zfc[6]=(zfctemp[3]&0x0f)+0x30;
 zfc[5]=(zfctemp[4]&0x0f)+0x30;         //日个位
 zfc[4]=((zfctemp[4]>>4)&0x0f)+0x30;       //日十位
 zfc[3]=(zfctemp[5]&0x0f)+0x30;         //月个位
 zfc[2]=((zfctemp[5]>>4)&0x0f)+0x30;       //月十位
 zfc[1]=(zfctemp[6]&0x0f)+0x30;        //年个位
 zfc[0]=((zfctemp[6]>>4)&0x0f)+0x30;       //年十位      
}

void LCDDISP(unsigned char *LCDdata){   //液晶显示16个字符
unsigned char t;
for (t=0;t<16;t++){
 if(t==0) {LCDD=0x80;delay(10);}
 else if(t==8) {LCDD=0xc0;delay(10);}     
 if(*LCDdata!='\0'){
  LCDRW=*LCDdata;
  delay(100);
  LCDdata++;  
  }
 }
}

void disp(void) interrupt 1{      //数码管显示中断服务子函数
  TH0=0xC4;  //定时器0初值装载
  TL0=0x00;  //定时器0初值装载         
  PA=smgd[sa];
  PD=smgb[0];
  delay(200);
  PD=smgb[1];

  PA=smgd[sb];
  PD=smgb[2];
  delay(200);
  PD=smgb[3];

  PA=smgd[sc];
  PD=smgb[4];
  delay(200);
  PD=smgb[5];
}

void c8255init(void){   //8255初始化
  PD=0x82;
 PC=0xff;
 PB=0xff;         
 PA=0Xff;
}

void SETDS1307(){

}

void main(void){ //主函数
  i2cinit();
  c8255init();
    readup();  //上限初始化
    readdown();  //下限初始化
 x=0;
 TMOD=0x01;  //设置定时器0工作在方式1
 TH0=0xC4;  //定时器0初值装载
 TL0=0x00;  //定时器0初值装载    
 EA=1;    //开CPU中断
  ET0=1;   //开定时器0中断
 TR0=1;   //启动定时/计数器0
 IT0=1;
 EX0=1;          //设置外部中断触发模式 电平触发
 ADCIN=0x00;  //通道0启动信号
 LCDINIT();
 writei2c(0xd0,0x00,0x00);  
 while(1){
  sc=x%10;
  sb=x%100/10;
  sa=x/100;
     if (((x>=m)|(x<=n))&(EX0==1)) {P1_5=0;Speaker();} else P1_5=1;
  switch (keyscan()){
   case 0x01:     up();break;  // 加1
   case 0x02:    down();break;  // 减1
   case 0x03:     pprom();break;  // 存储,如果LED1亮存储上限值,如果LED2亮存储下限值
   case 0x04:    EX0=1;break;     // 启动ADC转换
   case 0x05:    readup();break;     // 读取上限值
   case 0x06:   readdown();break;     // 读取下限值                                                               //
   case 0x07: SETDS1307();break;  // 调整时间
   case 0x08:          x=0;break;        // 清零
  }
  if (stopread1307==1) readi2cbyte(zfctemp,7,0xd0,0xd1,0x00);  //从DS1307里连续读出8个字节 
  read1307();
  LCDDISP(zfc);  
 }
}

 

详细资料联系QQ:81748606

回复

使用道具 举报

ID:61326 发表于 2014-5-4 10:58 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:48266 发表于 2014-5-16 18:07 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:99919 发表于 2015-12-22 09:12 | 显示全部楼层
谢谢分享,正准备用DS1307呢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表