找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5789|回复: 10
打印 上一主题 下一主题
收起左侧

共阳极怎么样改为共阴极时钟

[复制链接]
跳转到指定楼层
楼主
/**********************************WAYNE*********************************/
#include<reg52.h>
#include<intrins.h>
#include"DS18B20_3.H"       //18B20温度传感器头文件,18B20的服务程序都在这里
#define uchar unsigned char
#define uint  unsigned int
unsigned int distemp=8;       //红外接收返回值
unsigned char IRCOM[7];
unsigned char temp;
unsigned char sec, min, hour, day, month, year;
unsigned char aa=0;       //遥控器中间变量
unsigned char bb=1;       //显示界面中间变量
unsigned char cc=0;       //自动切换中间变量
unsigned char dd=0;       //掉电模式中间变量
unsigned char ee=0;
unsigned char flag;
uchar code table[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};       //数码管段码
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
sbit T_CLK = P3^5;       //实时时钟时钟线引脚
sbit T_IO = P3^6;       //实时时钟数据线引脚
sbit T_RST = P3^7;       //实时时钟复位线引脚
sbit Y1=P2^6;       //第一位数码管共阳极引脚
sbit Y2=P2^3;       //第二位数码管共阳极引脚
sbit Y3=P2^1;       //第三位数码管共阳极引脚
sbit Y4=P2^0;       //第四位数码管共阳极引脚
sbit led=P0^7;       //数码管小数点阴极引脚
sbit IRIN = P3^2;       //红外接收器数据线与单片机引脚之间的定义
/*********************************延时函数**************************************/
void Delay_1ms(uint i)       //1ms延时
{
        uchar x,j;
        for(j=0;j<i;j++)
        for(x=0;x<=148;x++);        
}
void delay1(unsigned char x)       //延时函数x*0.14MS
{
unsigned char i;
  while(x--)
{
  for (i = 0; i<13; i++) {}
}
}
/**********************************往DS1302写入1Byte数据*************************************/
void v_RTInputByte(uchar ucDa)
{
        uchar i;
        ACC = ucDa;
        T_RST = 1;
        for(i=8; i>0; i--)
        {
                T_IO = ACC0;
                T_CLK = 1;
                T_CLK = 0;
                ACC = ACC >> 1;
        }
}
/******************************从DS1302读取1Byte数据*****************************************/
uchar uc_RTOutputByte(void)
{
        uchar i;
        T_RST = 1;
        for(i=8; i>0; i--)
        {
                ACC = ACC >>1;
                T_IO=1;
                ACC7 = T_IO;
                T_CLK = 1;
                T_CLK = 0;
        }
        return(ACC);
}
/*******************************往DS1302写入数据****************************************/
void v_W1302(uchar ucAddr, uchar ucDa)
{
        T_RST = 0;
        T_CLK = 0;
        T_RST = 1;
        v_RTInputByte(ucAddr);       // 写地址
        _nop_();
        _nop_();
        v_RTInputByte(ucDa);       // 写1Byte数据
        T_CLK = 1;
        T_RST = 0;
}
/**********************************读取DS1302某地址的数据*************************************/
uchar uc_R1302(uchar ucAddr)
{
        uchar ucDa;
        T_RST = 0;
        T_CLK = 0;
        T_RST = 1;
        v_RTInputByte(ucAddr);       //写地址,命令
        _nop_();
        _nop_();
        ucDa = uc_RTOutputByte();       //读1Byte数据
        T_CLK = 1;
        T_RST = 0;
        return(ucDa);
}
/*********************************DEC码转换为BCD码**************************************/
uchar dectobcd(uchar dec)
{
        uchar bcd;
        bcd = 0;
        while(dec >= 10)
        {              
                dec -= 10;                        
                bcd++;
        }
        bcd <<= 4;
        bcd |= dec;
        return bcd;
}
/*******************************BCD码转换为DEC码****************************************/
uchar bcdtodec(uchar bcd)
{
        uchar data1;
        data1 = bcd & 0x0f;       //取BCD低4位
        bcd = bcd & 0x70;       //剔除BCD的最高位和低4位。
        data1 += bcd >> 1;
        data1 += bcd >> 3;       //用位移代替乘法运算
        return data1;
}
/*********************************往DS1302中写入数据**************************************/
void Write_DS1302Init(void)
{
        v_W1302(0x8e,0x00);       //屏蔽一下语句,则掉电走时有效;屏蔽则掉电走时失效,且每次上电后显示12:00(时)/2012(年)/1(月)1(日)
        v_W1302(0x80,0x00);       //写入秒
        v_W1302(0x82,0x00);       //写入分
        v_W1302(0x84,0x12);       //写入小时
        v_W1302(0x86,0x01);       //写入日
        v_W1302(0x88,0x01);       //写入月
        v_W1302(0x8a,0x00);       //写入星期
        v_W1302(0x8c,0x12);       //写入年
        v_W1302(0x8e,0x80);
}
/*********************************数码管位选码**************************************/
void Y_1()       //选通第一位数码管
{
  Y1=0;
  Y2=1;
  Y3=1;
  Y4=1;
}
void Y_2()       //选通第二位数码管
{
  Y1=1;
  Y2=0;
  Y3=1;
  Y4=1;
}
void Y_3()       //选通第三位数码管
{
  Y1=1;
  Y2=1;
  Y3=0;
  Y4=1;
}
void Y_4()       //选通第四位数码管
{
  Y1=1;
  Y2=1;
  Y3=1;
  Y4=0;
}
void Y_5()       //切断所有数码管,用于数码管消隐
{
  Y1=1;
  Y2=1;
  Y3=1;
  Y4=1;
}

/*******************************显示程序****************************************/
void Run_DS1302(void)
{
                v_W1302(0x8f, 0x00);
                sec = bcdtodec(uc_R1302(0x81));       //读出DS1302中的秒
                min = bcdtodec(uc_R1302(0x83));       //读出DS1302中的分
                hour = bcdtodec(uc_R1302(0x85));       //读出DS1302中的小时
                day = bcdtodec(uc_R1302(0x87));       //读出DS1302中的日
                month = bcdtodec(uc_R1302(0x89));       //读出DS1302中的月
                year = bcdtodec(uc_R1302(0x8d));       //读出DS1302中的年   
            v_W1302(0x8f,0x80);
                if(distemp == 0)
                {   distemp = 8;
                    aa++;
                }
                if(distemp ==7)
                {   distemp = 8;
                    ee++;
                }
                if(ee == 2)
                ee=0;
                if(aa==4)       //判断显示数据
                aa=0;
                if(aa == 0)
                {
                        bb = 1;       //显示时间
                }
                if(aa == 1)
                {
                        bb = 2;       //显示温度
                }
        if(aa == 2)
                {
                        bb = 3;       //显示年份
                }
                if(aa == 3)
                {
                        bb = 4;       //显示日期
                }
        if(ee == 1)
                bb = 5;
                if(bb == 1)       //时间显示界面
                {   if(hour / 10 % 10!=0)       //十位为0则不显示
                        {P1 = ~table[hour / 10 % 10];       //显示小时的十位数据
             led=1;
                         Y_1();       //选通第一位数码管
                         Delay_1ms(1);       //短暂停留
                         P1 = 0xff;       //数码管消隐
                          led=1;
                         Y_5();       //切断所有数码管
                        }
                        P1 = ~table[hour % 10];       //显示小时的个位数据
                        if(sec%2==0)       //判断是否秒闪烁
                        led=1;
                        else led=0;
                        Y_2();       //选通第二位数码管
                        Delay_1ms(1);       //短暂停留
            P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管
                        P1 = ~table[min / 10 % 10];       //显示分钟的十位数据
            if(sec%2==0)       //判断是否秒闪烁
                        led=1;
                        else led=0;
                        Y_3();       //选通第三位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管
                        P1 = ~table[min % 10];       //显示分钟的个位数据
            led=1;
                        Y_4();       //选通第四位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管
                }
                if(bb == 2)       //温度显示界面
                {
                        P1 = ~table[(flag-1) / 10 % 10];       //显示温度的十位数据
            led=1;
                        Y_2();       //选通第二位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管
                        P1 = ~table[(flag-1) % 10];       //显示温度的个位数据
            led=1;
                        Y_3();       //选通第三位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管
                        P1 = ~0x58;       //显示摄氏温度标志
                        led=0;
                        Y_4();       //选通第四位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管
                }
                if(bb == 3)       //年份显示界面
                {
                        P1 = ~0x6e;       //显示年份千位数据,默认为2
            led=1;
                        Y_1();       //选通第一位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管
                        P1 = ~0x77;       //显示年份百位数据,默认为0
            led=1;
                        Y_2();       //选通第二位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管
                    P1 = ~table[year / 10 % 10];       //显示年份十位数据
            led=1;
                        Y_3();       //选通第三位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管
                        P1 = ~table[year % 10];       //显示年份个位数据
            led=1;
                        Y_4();       //选通第四位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管
                }
                if(bb == 4)       //月日显示界面
                {   if(month / 10 % 10!=0)       //十位为0则不显示
                        {P1 = ~table[month / 10 % 10];       //显示月十位数据
             led=1;
                         Y_1();       //选通第一位数码管
                         Delay_1ms(1);       //短暂停留
             P1 = 0xff;       //数码管消隐
                           led=1;
                         Y_5();       //切断所有数码管
                         }
                        P1 = ~table[month % 10];       //显示月个位数据
            led=0;
                        Y_2();       //选通第二位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管                        
                        if(day / 10 % 10!=0)       //十位为0则不显示
                        {P1 = ~table[day / 10 % 10];       //显示日十位数据
             led=1;
                         Y_3();       //选通第三位数码管
                         Delay_1ms(1);       //短暂停留
                         P1 = 0xff;       //数码管消隐
                         led=1;
                         Y_5();       //切断所有数码管
                         }
                        P1 = ~table[day % 10];       //显示日个位数据
            led=1;
                        Y_4();       //选通第四位数码管
                        Delay_1ms(1);       //短暂停留
                        P1 = 0xff;       //数码管消隐
                        led=1;
                        Y_5();       //切断所有数码管                        
                }
                if(bb == 5)
                {  
                 P1=0xff;
                 if(sec%2==0)       //判断是否秒闪烁
                        led=1;
                        else led=0;
         Y_1();       //选通第四位数码管
                 Delay_1ms(1);       //短暂停留
                 }
}
/**********************************自动切换程序*************************************/
void zdqh()
{
if(distemp==6)
{distemp=8;
  cc++;
}
if(cc==2)       //切换为手动显示
cc=0;
if(cc==1)       //切换为自动循环显示
{
  if(sec%10==0)       //每10秒内,前7秒显示时间界面
  aa = 0;
  if(sec==7||sec==37)       //7秒和37秒切换为温度显示
  aa = 1;
  if(sec==17||sec==47)       //17秒和47秒切换为年份显示
  aa = 2;
  if(sec==27||sec==57)       //27秒和57秒切换为月日显示
  aa = 3;
}
}
/*********************************调节程序**************************************/
void tj()
{
if(distemp == 1)       //判断按下的键值
{distemp=8;       //返回值回位
  if(bb==1)       //判断当前显示界面
  {
   hour++;       //小时加一调节
   if(hour==24)       //限制小时数据在0~23之间
   hour=0;
   temp=dectobcd(hour);       //将十进制数转换成十六禁止数
   v_W1302(0x8e,0x00);       //禁止写保护
   v_W1302(0x84,temp);       //写入小时数据
   v_W1302(0x80,0x00);
   v_W1302(0x8e,0x80);       //打开写保护
  }
  if(bb==4)       //判断当前显示界面
  {
   month++;       //月加一调节
   if(month==13)       //限制月数据在1~12之间
   month=1;
   temp=dectobcd(month);       //将十进制数转换成十六禁止数
   v_W1302(0x8e,0x00);       //禁止写保护
   v_W1302(0x88,temp);       //写入月数据
   v_W1302(0x8e,0x80);       //打开写保护
  }
}
if(distemp == 2)       //判断按下的键值
{distemp=8;       //返回值回位
  if(bb==1)       //判断当前显示界面
  {
   min++;//分钟加一调节
   if(min==60)//限制分钟数据在0~59之间
   min=0;
   temp=dectobcd(min);//将十进制数转换成十六禁止数
   v_W1302(0x8e,0x00);//禁止写保护
   v_W1302(0x82,temp);//写入分钟数据
   v_W1302(0x80,0x00);
   v_W1302(0x8e,0x80);//打开写保护
  }
  if(bb==3)//判断当前显示界面
  {
   year++;//年份加一调节
   if(year==100)//限制年份数据在0~99之间
   year=0;
   temp=dectobcd(year);//将十进制数转换成十六禁止数
   v_W1302(0x8e,0x00);//禁止写保护
   v_W1302(0x8c,temp);//写入年数据
   v_W1302(0x8e,0x80);//打开写保护
  }
  if(bb==4)//判断当前显示界面
  {
   day++;       //日加一调节
   if(day==32)       //限制日数据在1~31之间
   day=1;
   temp=dectobcd(day);       //将十进制数转换成十六禁止数
   v_W1302(0x8e,0x00);       //禁止写保护
   v_W1302(0x86,temp);       //写入日数据
   v_W1302(0x8e,0x80);       //打开写保护
  }
}
if(distemp == 3)       //判断按下的键值
{distemp=8;       //返回值回位
  if(bb==1)       //判断当前显示界面
  {
   hour--;       //小时减一调节
   if(hour==-1)       //限制小时数据在0~23之间
   hour=23;
   temp=dectobcd(hour);       //将十进制数转换成十六禁止数
   v_W1302(0x8e,0x00);       //禁止写保护
   v_W1302(0x84,temp);       //写入小时数据
   v_W1302(0x80,0x00);
   v_W1302(0x8e,0x80);       //打开写保护
  }
  if(bb==4)       //判断当前显示界面
  {
   month--;       //月减一调节
   if(month==0)       //限制月数据在1~12之间
   month=12;
   temp=dectobcd(month);       //将十进制数转换成十六禁止数
   v_W1302(0x8e,0x00);       //禁止写保护
   v_W1302(0x88,temp);       //写入月数据
   v_W1302(0x8e,0x80);       //打开写保护
  }
}
if(distemp == 4)       //判断按下的键值
{distemp=8;       //返回值回位
  if(bb==1)       //判断当前显示界面
  {
   min--;       //分钟减一调节
   if(min==-1)       //限制分钟数据在0~59之间
   min=59;
   temp=dectobcd(min);       //将十进制数转换成十六禁止数
   v_W1302(0x8e,0x00);       //禁止写保护
   v_W1302(0x82,temp);       //写入分钟数据
   v_W1302(0x80,0x00);
   v_W1302(0x8e,0x80);       //打开写保护
  }
  if(bb==3)       //判断当前显示界面
  {
   year--;       //年份减一调节
   if(year==-1)       //限制年份数据在0~99之间
   year=99;
   temp=dectobcd(year);       //将十进制数转换成十六禁止数
   v_W1302(0x8e,0x00);       //禁止写保护
   v_W1302(0x8c,temp);       //写入年数据
   v_W1302(0x8e,0x80);       //打开写保护
  }
  if(bb==4)       //判断当前显示界面
  {
   day--;       //日减一调节
   if(day==0)       //限制日数据在1~31之间
   day=31;
   temp=dectobcd(day);       //将十进制数转换成十六禁止数
   v_W1302(0x8e,0x00);       //禁止写保护
   v_W1302(0x86,temp);       //写入日数据
   v_W1302(0x8e,0x80);       //打开写保护
  }
}
}
/*******************************掉电模式程序****************************************/
void xmms()
{
if(dd == 1)       //单片机进入掉电工作模式,该模式下只有首位数码管的小数点常亮
{
  P0=~0xff;       //在掉电模式下,只有第一位数码管的小数点亮
  led=1;
  Y_5();
  aa=0;
  ee=0;
  PCON=0x02;       //设置掉电模式寄存器,这句一定要放在该子程序的最后
}
}
/********************************自动校时***************************************/
void zdjs()
{
if(hour==3&&min==0&&sec==30)
   {
        v_W1302(0x8e,0x00);      
        v_W1302(0x80,0x00);
    v_W1302(0x8e,0x80);
    }
}
/********************************主函数***************************************/
void Main(void)
{   
    EA=1;       //打开总中断
        EX0=1;       //允许外部0中断
    IT0=1;       //设置外部中断0为边沿方式触发
    IRIN=1;
        Write_DS1302Init();
        while(1)       //无限循环以下子程序
        {
         Run_DS1302();       //显示程序
         flag=ReadTemperature();       //将18b2头文件运行返回的函数结果送到变量flag中,用于显示
         tj();       //调节程序
         xmms();       //休眠模式
         zdqh();       //自动切换
         zdjs();       //自动校时
         }
}
/*********************红外接收程序**********************/
void IR_IN() interrupt 0       //外部中断0
{
  unsigned char p,q,R=0;
  EA = 0;
  delay1(15);
  if (IRIN==1)
   { EA =1;
         return;
        }                  
  while (!IRIN)            
    {delay1(1);}
  for (p=0;p<4;p++)         
  {
   for (q=0;q<8;q++)      
   {
    while (IRIN)            
     {delay1(1);}
    while (!IRIN)        
     {delay1(1);}
    while (IRIN)         
     {
      delay1(1);
      R++;           
      if (R>=30)
           { EA=1;
             return;}               
      }                                 
     IRCOM[p]=IRCOM[p] >> 1;                 
     if (R>=8) {IRCOM[p] = IRCOM[p] | 0x80;}
     R=0;
  }                        
}                          
   if (IRCOM[2]!=~IRCOM[3])
   { EA=1;
     return; }
   switch(IRCOM[2])
   {
                   case 0x07:       //显示切换键
                        distemp = 0;
                        break;
                case 0x44:       //左加一键
                        distemp = 1;
                        break;
                case 0x45:       //右加一键
                        distemp = 2;
                        break;
                case 0x46:       //左减一键
                        distemp = 3;
                        break;
                case 0x47:       //右减一键
                        distemp = 4;
                        break;
        case 0x16:       //掉电模式开关键
                        distemp = 5;
                        break;
                case 0x10:       //自动切换开关键
                        distemp = 6;
                        break;
                case 0x1c:       //待机模式开关键
                        distemp = 7;
                        break;
   }
    if(distemp == 5)       //开启、关闭掉电模式,因掉电模式只能由外部中断唤醒,所以下面的程序必须放在中断函数中
    {distemp = 8;       //返回值回位
     dd++;
    }
    if(dd == 2)
    dd = 0;
        if(dd == 0)       //退出掉电模式
        {PCON=0x00;       //设置掉电模式工作寄存器
         }
        if(dd == 1)       //掉电模式下,其他按键无效
        distemp = 8;       //不返回任何键值
        if(ee==1)
         {if(distemp==0||distemp==1||distemp==2||distemp==3||distemp==4||distemp==6)
          distemp = 8;
          }
        EA = 1;       //打开总中断
}

IMG_20161111_172106.jpg (3.15 MB, 下载次数: 86)

IMG_20161111_172106.jpg
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:146910 发表于 2016-12-1 13:00 | 只看该作者
没有人回,怎么改共阴极加三极管驱动,
回复

使用道具 举报

板凳
ID:1 发表于 2016-12-3 23:25 | 只看该作者
只改数码管吗?这需要电路和程序一起改,程序里面要改段码
回复

使用道具 举报

地板
ID:146910 发表于 2016-12-4 11:33 | 只看该作者
admin 发表于 2016-12-3 23:25
只改数码管吗?这需要电路和程序一起改,程序里面要改段码

只改共阴极数码管,电路三极管驱动会改,
回复

使用道具 举报

5#
ID:111634 发表于 2016-12-4 13:16 | 只看该作者
提法有错!时钟并无共阳共阴之分,LED数码管却有共阳共阴之分。
回复

使用道具 举报

6#
ID:148496 发表于 2016-12-4 18:41 | 只看该作者
数码管是共阴极 还是共阳极生产出来就定了  你是想表达啥问题?
回复

使用道具 举报

7#
ID:152375 发表于 2016-12-5 20:12 来自手机 | 只看该作者
把发送的一改为0
回复

使用道具 举报

8#
ID:146910 发表于 2016-12-5 21:12 | 只看该作者
艾格CG 发表于 2016-12-4 18:41
数码管是共阴极 还是共阳极生产出来就定了  你是想表达啥问题?

上面的程序是共阳极了,想改为共阴极的
回复

使用道具 举报

9#
ID:152408 发表于 2016-12-5 21:22 | 只看该作者
怎么改
回复

使用道具 举报

10#
ID:153199 发表于 2016-12-17 09:37 | 只看该作者
需要把数码管的码表改一下,程序改,三级管驱动改
回复

使用道具 举报

11#
ID:155379 发表于 2016-12-17 09:43 | 只看该作者
不知道你用什么驱动。如果用三极管换一下。程序把电平改改应该可以。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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