最好的电子音响科技diy制作网站

haoDIY_音响电子电脑科技DIY小制作发明

当前位置: 主页 > 最新DIY >

24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发](3)

时间:2017-07-31 21:25来源:数码之家 作者:yanzeyuan 点击:
用于指示星期和冒号的氖灯灯管做好了,这下可以跟辉光管完美搭配了,因为有了底座,所以很容易固定在电路板上,所以马上把它们各就各位,效果出乎我的想想,实在是太般配了。 看一下整体效果吧,高度几乎一致,而且

24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 


用于指示星期和冒号的氖灯灯管做好了,这下可以跟辉光管完美搭配了,因为有了底座,所以很容易固定在电路板上,所以马上把它们各就各位,效果出乎我的想想,实在是太般配了。 
看一下整体效果吧,高度几乎一致,而且氖灯位于顶端,发光的位置也刚好,并且粗细作为小点来说刚刚合适,不粗也不细。 
SHOW一下: 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发]  

六、编写译码电路驱动程序 

74HC595是很常用的器件,3线串口通讯,每个驱动芯片提供8个译码输出,以前常用于LED数码管的驱动,加上小数点正好8段。但这次使用的是辉光管,每显示一个数字就需要有一个驱动,所以为了6个辉光管每个数字都能亮,一共需要60个译码输出,这就要用到8片74HC595芯片。 
这颗芯片很常用,看了一下DATASHEET,很快就做好了通讯程序,下面我把74HC595的通讯代码及控制各辉光管显示数字的代码部分贴出来: 
/******************************************************************************************************** 
** 功能描述: 向74HC595发送数据 
** 入口参数: count: 发送数据的位数 
** dat: 发送的数据(MAX 16Bit) 
** 创 建 者: 严泽远 
** 创建时间: 2010-11-21 13:09 
** 版 本: v1.0.0 
********************************************************************************************************/ 

void send_data(uchar count,uint dat) 

for(;count>0;count--) 

DATA = dat&0x0001;_nop_(); 
SHCP = 1;_nop_();SHCP = 0;_nop_(); 
dat>>=1; 

}
 
/******************************************************************************************************** 
** 功能描述: 刷新QS30-1辉光管的显示数字 
** 入口参数: N1: 第一位显示的数 
** N2: 第一位显示的数 
** N3: 第一位显示的数 
** N4: 第一位显示的数 
** N5: 第一位显示的数 
** N6: 第一位显示的数 
** 创 建 者: 严泽远 
** 创建时间: 2010-11-21 14:23 
** 版 本: v1.0.0 
********************************************************************************************************/ 

void DispNum(uchar N1,uchar N2,uchar N3,uchar N4,uchar N5,uchar N6) 

uchar buf,buf2; 
if(N1>9) buf = 0x00; 
else buf = 0x08>>N1; 
send_data(8,buf); //U1
 
if(N1>9) buf = 0x00; 
else buf = 0x80>>(N1-4); 
if(N2>9) buf2= 0x00; 
else buf2= 0x02>>N2; 
send_data(8,buf|buf2); //U2
 

if(N2>9) buf = 0x00; 
else buf = 0x80>>(N2-2); 
send_data(8,buf); //U3
 

if(N3>9) buf = 0x00; 
else buf = 0x80>>N3; 
send_data(8,buf); //U4
 

if(N3>9) buf = 0x00; 
else buf = 0x80>>(N3-8); 
if(N4>9) buf2= 0x00; 
else buf2= 0x20>>N4; 
send_data(8,buf|buf2); //U5
 

if(N4>9) buf = 0x00; 
else buf = 0x80>>(N4-6); 
if(N5>9) buf2= 0x00; 
else buf2= 0x08>>N5; 
send_data(8,buf|buf2); //U6
 

if(N5>9) buf = 0x00; 
else buf = 0x80>>(N5-4); 
if(N6>9) buf2= 0x00; 
else buf2= 0x02>>N6; 
send_data(8,buf|buf2); //U7
 

if(N6>9) buf = 0x00; 
else buf = 0x80>>(N6-2); 
send_data(8,buf); //U8
 
STCP = 1;_nop_();STCP = 0;_nop_(); //数据锁存
} 
这段程序调试成功了以后就能够在每个辉光管上显示任意字符了,有模有样的效果出来啦,SHOW一下: 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 

七、编写DS1302时钟芯片读写程序 
  
DS1302也是很常用的一款时钟芯片,外围元器件非常少,仅一个电池,一颗晶体,一颗电容即可,通过3线与MCU通讯, 具体介绍网上一搜一大把,时序也很简单,以前在其他作品上用过这个芯片,程序也很简单,调试几分钟就OK,下面我也把代码贴出来,可以给朋友们做个参考: 

/****************************************Copyright (c)************************************************** 
** 
** 项目名称: QS30-1辉光钟 目标板试验程序 
** 文件名称: DS1302.c 
** 模块功能: 实现DS1302时钟芯片的完全控制 
** 
**------------------------------------------------------------------------------------------------------
 

** 创 建 者: 严泽远 
** E-mail : 
yanzeyuan@163.com 

** QQ : 6626209 
** Mobile : 18602007878 
** 创建时间: 2010-11-19 
** 版 本: v1.0.0 
** 描 述: 基础程序 
** 
********************************************************************************************************/
 

#include <C8051F310.h> //加载C8051F310.h头文件 
#include <Define.h> //加载Define.h头文件 
#include <DS1302Function.h> //加载DS1302Function.h头文件 
#include <DS1302Extern.h> //加载DS1302Extern.h头文件
 

/******************************************************************************************************** 
** 功能描述: 往DS1302写入1Byte数据 
** 入口参数: ucDa 写入的数据 
** 创 建 者: 严泽远 
** 创建时间: 2010-02-05 23:52 
** 版 本: v2.1.3 
********************************************************************************************************/ 

void v_RTInputByte(uchar ucDa) 

xdata uchar i; 
xdata uchar j; 
j = ucDa; 
for(i=8; i>0; i--) 

T_IO = (j&0x01); /*相当于汇编中的 RRC */ 
T_CLK = 1; 
_nop_();_nop_(); 
T_CLK = 0; 
j=j>>1; 


/******************************************************************************************************** 
** 功能描述: 从DS1302读取1Byte数据 
** 出口参数: ACC 
** 创 建 者: 严泽远 
** 创建时间: 2010-02-06 00:11 
** 版 本: v2.1.3 
********************************************************************************************************/ 

uchar uc_RTOutputByte(void) 

uchar i; 
uchar j; 
for(i=8; i>0; i--) 

j=j>>1; 
if(T_IO){j|=0x80;}else{j&=0x7f;} 
T_CLK = 1; 
_nop_();_nop_(); 
T_CLK = 0; 

return(j); 

/******************************************************************************************************** 
** 功能描述: 往DS1302写入数据 
** 入口参数: ucAddr: DS1302地址 
** ucDa: 要写的数据 
** 创 建 者: 严泽远 
** 创建时间: 2010-02-06 00:11 
** 版 本: v2.1.3 
********************************************************************************************************/ 

void v_W1302(uchar ucAddr, uchar ucDa) 

T_RST = 0; 
T_CLK = 0; 
T_RST = 1; 
_nop_();_nop_(); 
v_RTInputByte(ucAddr); /* 地址,命令 */ 
v_RTInputByte(ucDa); /* 写1Byte数据*/ 
T_CLK = 1; 
T_RST =0; 

/******************************************************************************************************** 
** 功能描述: 读取DS1302某地址的数据 
** 入口参数: ucAddr: DS1302地址 
** 创 建 者: 严泽远 
** 创建时间: 2010-02-06 00:17 
** 版 本: v2.1.3 
********************************************************************************************************/ 

uchar uc_R1302(uchar ucAddr) 

uchar ucDa; 
T_RST = 0; 
T_CLK = 0; 
T_RST = 1; 
_nop_();_nop_(); 
v_RTInputByte(ucAddr); /* 地址,命令 */ 
ucDa = uc_RTOutputByte(); /* 读1Byte数据 */ 
T_CLK = 1; 
T_RST =0; 
return(ucDa); 

/******************************************************************************************************** 
** 功能描述: 设置初始时间 
** 入口参数: pSecDa: 初始时间地址。初始时间格式为: 秒 分 时 日 月 星期 年 
** 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B 
** 创 建 者: 严泽远 
** 创建时间: 2010-02-06 01:02 
** 版 本: v2.1.3 
********************************************************************************************************/ 

void v_Set1302(uchar *pSecDa) 

uchar i; 
uchar ucAddr = 0x80; 
v_W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/ 
for(i =7;i>0;i--) 

v_W1302(ucAddr,*pSecDa); /* 秒 分 时 日 月 星期 年 */ 

pSecDa++; 
ucAddr +=2; 

v_W1302(0x8e,0x80); /* 控制命令,WP=1,写保护?*/ 

/******************************************************************************************************** 
** 功能描述: 读取DS1302当前时间 
** 入口参数: ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年 
** 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B 
** 创 建 者: 严泽远 
** 创建时间: 2010-02-06 01:02 
** 版 本: v2.1.3 
********************************************************************************************************/ 

void v_Get1302(uchar ucCurtime[]) 

uchar i; 
uchar ucAddr = 0x81; 
for (i=0;i<7;i++) 

ucCurtime
 = uc_R1302(ucAddr);/*格式为: 秒 分 时 日 月 星期 年 */ 
ucAddr += 2; 

}
 

七、编写18B20温度传感器读写程序 

18B20我就更不用多介绍了,常用的不得了,他的封装就像一个直插的三极管一样,只有三个管脚,电源两个脚,通讯只需要一个管脚。这也是它的特点,单线接口。而且不需要任何外围元器件,温度测量范围是-55℃至125℃,所以我说用在测量室温里面的确有点大材小用,呵呵。 
虽然读写都用一个口线,但是通讯时序并不复杂,也很简单,很容易调试出来,当然在这里我只用了读取温度的功能,其他还有很多功能比如温度告警设置,唯一序列号读取等等都没有用,程序还是很简单的,我也贴出来,有用的朋友们可以借鉴一下。 


/****************************************Copyright (c)************************************************** 
**     
** 项目名称:   QS30-1辉光钟 目标板试验程序 
** 文件名称:   18B20.c 
** 模块功能:   实现18B20温度传感器的温度读取 
** 
**------------------------------------------------------------------------------------------------------
 
**  创 建 者:   严泽远 
** E-mail  :   
[email=yanzeyuan@163.com]yanzeyuan@163.com[/email] 
** QQ  :   6626209 
** Mobile :   18602007878 
** 创建时间:   2010-11-19 
** 版    本:   v1.0.0 
** 描    述:   基础程序 
** 
********************************************************************************************************/
 
#include <C8051F310.h>   //加载C8051F310.h头文件 
#include <Define.h>    //加载Define.h头文件
 
uint temperature;    //温度全局变量 
/******************************************************************************************************** 
** 功能描述:   简单的延时程序   
** 创 建 者:   严泽远 
** 创建时间:   2010-11-17 20:52 
** 版    本:   v1.0.0 
********************************************************************************************************/ 
void delay_18b20(uchar N) 

uchar i,j; 
for(j=0;j<40;j++) 
for(i=0;i<N;i++) 
{;} 
}
 
/******************************************************************************************************** 
** 功能描述:   DS18B20初始化子程序 
** 创 建 者:   严泽远 
** 创建时间:   2010-11-17 21:03 
** 版    本:   v1.0.0 
********************************************************************************************************/ 
void Init_DS18B20(void) 

unsigned char result_18b20;  //用来存储DQ的脉冲 
do{ 
  DQ=0;       //拉低总线,发出复位脉冲 
  delay_18b20(25);    //延时530us 
  DQ=1;       //释放总线,等待ds18b20的应答脉冲 
  delay_18b20(5);    //等待110us 
  result_18b20=DQ;    //读取ds18b20的应答脉冲 
  delay_18b20(15);    //等待周期结束 
}while(result_18b20==1);   //若ds18b20无应答,则继续发复位脉冲 

/******************************************************************************************************** 
** 功能描述:   向DS18B20读一字节数据 
** 出口参数:   读取的一个字节 
** 创 建 者:   严泽远 
** 创建时间:   2010-11-17 20:55 
** 版    本:   v1.0.0 
********************************************************************************************************/ 
unsigned char ReadOneChar(void) 

unsigned char i,j; 
unsigned char dat=0; 
for(i=8;i>0;i--) 

  dat>>=1;      //右移一位 
  DQ=0;       //拉低总线 
  for(j=2;j>0;j--);    //延时4us 
   DQ=1;      //释放总线,以让DS18B20把数据传输到单总线上 
  for(j=4;j>0;j--);    //延时8us 
   if(DQ==1)     //读取ds18b20发来的数据,从低位读起 
    dat|=0x80;    //将读到的数据保存在d中 
  delay_18b20(2);    //延时等待读周期结束 
  DQ=1; 

   return(dat);      //返回读到的数据 
}
 

/******************************************************************************************************** 
** 功能描述:   向DS18B20写一字节数据 
** 如口参数:   dat: 要写入的一个字节 
** 创 建 者:   严泽远 
** 创建时间:   2010-11-17 21:09 
** 版    本:   v1.0.0 
********************************************************************************************************/ 
void WriteOneChar(unsigned char dat) 

   unsigned char i,j; 
   for(i=8;i>0;i--) 
   { 
   DQ=0;      //拉低总线 
   for(j=2;j>0;j--);   //延时4us 
    DQ=dat&0x01;   //主机在总线上写数据传送到ds18b20 
   delay_18b20(3);   //延时等待写周期结束 
   DQ=1;      //重新将总线拉高 
     dat>>=1;     //右移一位 
   } 

/******************************************************************************************************** 
** 功能描述:   向DS18B20读温度值并转换成实际温度 
** 创 建 者:   严泽远 
** 创建时间:   2010-11-17 21:49 
** 版    本:   v1.0.0 
********************************************************************************************************/ 
void ReadTemperature() 

uchar tempL,tempH; 
  
Init_DS18B20();     //初始化ds18b20 
WriteOneChar(0xcc);    //发送读指令跳过rom 
WriteOneChar(0x44);    //发送指令启动温度转换 
Init_DS18B20();     //初始化ds18b20 
WriteOneChar(0xcc);    //发送读指令匹配rom      
WriteOneChar(0xbe);    //发送指令开始读取温度 
tempL=ReadOneChar();    //读取温度值低位 
tempH=ReadOneChar();    //读取温度值高位 
Init_DS18B20();     //再发送一次复位脉冲,终止温度的读取 
temperature=((tempH*256)+tempL);//*0.625;   //转换成实际温度 
temperature/=16; 


八、测试红外线遥控器发射和接受,编写红外遥控器解码程序 

为了让复古的辉光管与现代科技完美结合,我花了几块钱淘了一个很可爱的红外线遥控器,打算用它来实现所有的控制功能。包括开关机、调整时间等等。红外遥控在十年前要搞解码会很麻烦,要用红外线接收管,然后要用一大堆电路去解调红外线编码。现在方便了,直接用38B的红外线接收头,三个脚,两个接电源,另外一个在接收到红外线遥控编码的时候就直接将编码输出出来,可以直接接到MCU的输入口上进行软件处理。 
我在电路板上设计了一个位置用于安装红外线接收头,看一下,就在冒号的底下: 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 

24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 



红外线解码程序最好是用MCU的外部中断口去连接红外接收头的数据脚,这样软件会好做一些,可惜我用的MCU不带外部中断输入,所以我在MCU上随便找了一个IO,打算用定时器加软件查询的办法去对红外线数据进行解码。 
首先先认识一下红外线编码格式,我们所使用的遥控器为NEC格式的码(最常用的编码格式),通过红外接收头出来的电平是这样的,我用示波器给掐出来分析一下: 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 

24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 

由上面可以看出来,这是一个标准的完整红外线遥控数据,其中由引导码+16位系统码+8位按键码+8位按键反码组成。 
其中引导码由9ms的低电平和4.5ms的高电平组成。 
数据码为一段560us低电平,后引一段高电平,高电平长度为1680us时表示该BIT为1,高电平长度为560us时表示该BIT为0。 
如果我们按着遥控器的按键不放,那么遥控器会送出一段重复码,表示该按键没有释放, 重复码由9ms的低电平和2.25ms的高电平作开头,然后跟着一个脉冲。 
要精确的解码,最重要的是要去精确测量这些电平的时间长短,所以要产生一个用于测量的标准时间出来,所以我用了MCU的一个定时器,产生一个100us的标准时间,看一下测量的结果,好准啊,呵呵: 
24小时的感动(古典版I) 自制QS30-1辉光电子钟 附百图[首发] 


接下来就是把所有遥控器的按键对应的编码解出来,然后根据按下的键是哪个,执行相应的功能就好了。 
在这里我把用定时器2中断去查询解码的一段程序贴出来,有需要的朋友可以借鉴一下。 


/******************************************************************************************************** 
** 功能描述: T2定时器计时完毕后执行的红外线数据解码函数 
** 创 建 者: 严泽远 
** 创建时间: 2010-11-19 01:45 
** 版 本: v1.0.0 
********************************************************************************************************/ 

void Timer2Interrupt() interrupt 5 

bit F_Pulse = 0; //是否收到一个数据 
TF2H=0; //清零中断标志位
 
if(IR_LastLH==1 && IR==0) //一个脉冲完毕 

switch(IR_State) 

case WAIT: //等待状态 
if((IR_LC>=85 && IR_LC<=95) && (IR_HC>=40 && IR_HC<=50)) //新引导码由9ms的低电平和4.5ms的高电平组成 

IR_State = RECIVE; //当前为开始接收数据状态 
IR_BufByte = 0; //从第一个数据开始接收 
IR_BufBit = 0; //从第零位数据开始接收 
IR_Rep = 0; //重复码数量减少 

if((IR_LC>=85 && IR_LC<=95) && (IR_HC>=17 && IR_HC<=27)) //重复码由9ms的低电平,2.25ms的高电平,跟着是一个短脉冲 

F_NewIRdata = 1; //有了新红外数据 
if(IR_Rep<255) IR_Rep++; //重复码数量增加 

break; 
case RECIVE: //开始接受数据状态 
if((IR_LC>=3 && IR_LC<=7) && (IR_HC>=14 && IR_HC<=18)) //数据码为一段560us低电平,后引一段高电平,高电平长度为1680us时为1 

IR_Buf[IR_BufByte] <<= 1; //左移一位 
IR_Buf[IR_BufByte] |= 0x01; //或上数据 

if((IR_LC>=3 && IR_LC<=7) && (IR_HC>=3 && IR_HC<=7)) //数据码为一段560us低电平,后引一段高电平,高电平长度为560us时为0

IR_Buf[IR_BufByte] <<= 1; //左移一位 

IR_BufBit++; //数据位数增加 
if(IR_BufBit>=8) //如果记录了8位数据 

IR_BufBit = 0; //开始计算另一字节的第零位数据 
IR_BufByte++; //字节数增加 

if(IR_BufByte>3) //如果记录满了4个字节则开始退出分析按键码 

IR_State = WAIT; //恢复到等待接受红外信号状态 
F_NewIRdata = 1; //有了新红外数据 


IR_LC=0; IR_HC=0; //复位电平计数值 

if(IR==0) {IR_LC++;IR_LastLH=0;IR_HC=0;} //低电平时长计数 
if(IR_LC>100) {IR_LC=100; IR_State=WAIT;} //如果低电平连续超过10ms即为非正常数据 
if(IR==1) {IR_HC++;IR_LastLH=1;} //高电平时长计数 
if(IR_HC>100) {IR_HC=100; IR_State=WAIT;} //如果高电平连续超过10ms即为非正常数据
 

(责任编辑:admin)
织梦二维码生成器
顶一下
(0)
0%
踩一下
(0)
0%
相关文章
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
推荐内容