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一下:
七、编写DS1302时钟芯片读写程序
DS1302也是很常用的一款时钟芯片,外围元器件非常少,仅一个电池,一颗晶体,一颗电容即可,通过3线与MCU通讯, 具体介绍网上一搜一大把,时序也很简单,以前在其他作品上用过这个芯片,程序也很简单,调试几分钟就OK,下面我也把代码贴出来,可以给朋友们做个参考:
/Copyright (c)
项目名称: QS30-1辉光钟 目标板试验程序
文件名称: DS1302.c
模块功能: 实现DS1302时钟芯片的完全控制
------------------------------------------------------------------------------------------------------
创 建 者: 严泽远
E-mail :
:
Mobile :
创建时间: 2010-11-19
版 本: v1.0.0
描 述: 基础程序
/
#include
#include
#include
#include
/
功能描述: 往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[i] = uc_R1302(ucAddr);/*格式为: 秒 分 时 日 月 星期 年 */
ucAddr += 2;
}
}
七、编写18B20温度传感器读写程序
18B20我就更不用多介绍了,常用的不得了,他的封装就像一个直插的三极管一样,只有三个管脚,电源两个脚,通讯只需要一个管脚。这也是它的特点,单线接口。而且不需要任何外围元器件,温度测量范围是-55℃至125℃,所以我说用在测量室温里面的确有点大材小用,呵呵。
虽然读写都用一个口线,但是通讯时序并不复杂,也很简单,很容易调试出来,当然在这里我只用了读取温度的功能,其他还有很多功能比如温度告警设置,唯一序列号读取等等都没有用,程序还是很简单的,我也贴出来,有用的朋友们可以借鉴一下。
/Copyright (c)
项目名称: QS30-1辉光钟 目标板试验程序
文件名称: 18B20.c
模块功能: 实现18B20温度传感器的温度读取
------------------------------------------------------------------------------------------------------
创 建 者: 严泽远
E-mail :
:
Mobile :
创建时间: 2010-11-19
版 本: v1.0.0
描 述: 基础程序
/
#include
#include
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
}
/
功能描述: 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的输入口上进行软件处理。
我在电路板上设计了一个位置用于安装红外线接收头,看一下,就在冒号的底下:
红外线解码程序最好是用MCU的外部中断口去连接红外接收头的数据脚,这样软件会好做一些,可惜我用的MCU不带外部中断输入,所以我在MCU上随便找了一个IO,打算用定时器加软件查询的办法去对红外线数据进行解码。
首先先认识一下红外线编码格式,我们所使用的遥控器为NEC格式的码(最常用的编码格式),通过红外接收头出来的电平是这样的,我用示波器给掐出来分析一下:
由上面可以看出来,这是一个标准的完整红外线遥控数据,其中由引导码+16位系统码+8位按键码+8位按键反码组成。
其中引导码由9ms的低电平和4.5ms的高电平组成。
数据码为一段560us低电平,后引一段高电平,高电平长度为1680us时表示该BIT为1,高电平长度为560us时表示该BIT为0。
如果我们按着遥控器的按键不放,那么遥控器会送出一段重复码,表示该按键没有释放, 重复码由9ms的低电平和2.25ms的高电平作开头,然后跟着一个脉冲。
要精确的解码,最重要的是要去精确测量这些电平的时间长短,所以要产生一个用于测量的标准时间出来,所以我用了MCU的一个定时器,产生一个100us的标准时间,看一下测量的结果,好准啊,呵呵:
功能描述: T2定时器计时完毕后执行的红外线数据解码函数
创 建 者: 严泽远
创建时间: 2010-11-19 01:45
版 本: v1.0.0
/
void Timer2Interrupt() interrupt 5
{
bit F_Pulse = 0; //是否收到一个数据
TF2H=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_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即为非正常数据
ShowLED++;
if(ShowLED>=40) ShowLED=0;
if(ShowLED
else BLUELED = !ShowLEDBit;
}
九、使用红外线遥控器实现相应功能
十、大功告成,为辉光钟上一个底板,就用镀金的PCB板做外壳。
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/54565.html