- //-----------------------------------------------------------------
- // 名称: 带日历时钟及温度显示的电子万年历
- //-----------------------------------------------------------------
- // 说明: 本例使用了DS1302读取日期时间,用TC72获取温度数据
- // 通过74HC595驱动数码管显示.
- //
- //-----------------------------------------------------------------
- #include <reg51.h>
- #include <intrins.h>
- #include <stdio.h>
- #include <string.h>
- #define INT8U unsigned char
- #define INT16U unsigned int
- const INT8U SEG_CODE[]= //0~9的段码,摄氏度段码(2字节),黑屏段码,负号段码
- { 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0xC6,0x9C,0xFF,0xBF};
- INT8U DateTime[7] = {5,4,3,2,1,5,12}; //假定时间12年1月2日,3点,4分5秒
- sbit DS = P3^0; //串行数据输入
- sbit SH_CP = P3^1; //移位时钟脉冲
- sbit ST_CP = P3^2; //输出锁存器控制脉冲
- extern void Init_DS1302();
- extern void GetDateTime();
- extern void SetDateTime();
- extern INT8U CurrDateTime[];
- extern void Config_TC72();
- extern float Read_TC72_Temperature();
- //所有数码管的显示缓冲(年有高2位固定为20),最后2位固定为摄氏度段码索引
- INT8U disp_buff[21] = {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,10};
- //-----------------------------------------------------------------
- // 延时函数
- //-----------------------------------------------------------------
- void delay_ms(INT16U x) { INT8U t; while(x--) for(t = 0; t<120; t++);}
- //-----------------------------------------------------------------
- // 1字节数据串行输入595子程序
- //-----------------------------------------------------------------
- void Serial_Input_595(INT8U d)
- {
- INT8U i;
- for(i=0;i<8;i++)
- { d<<=1;DS=CY;
- SH_CP=0;_nop_();_nop_();
- SH_CP=1;_nop_();_nop_();
- }
- SH_CP=0;
- }
- //-----------------------------------------------------------------
- // 595并行输出子程序
- //-----------------------------------------------------------------
- void Parallel_Output_595()
- {
- ST_CP=0;_nop_();_nop_();
- ST_CP=1;_nop_();_nop_();
- ST_CP=0;_nop_();_nop_();
- }
- //------------------------------------------------------------------
- // 主程序
- //------------------------------------------------------------------
- void main()
- {
- INT8U i,j,len;char t_buff[6],c;INT8U curr_second=0xFF;
- TMOD=0x01;
- TH0=(INT16U)(-11.0592/12*50000)>>8;
- TL0=(INT16U)(-11.0592/12*50000)&0xFF;
- IE=0x82;
- Init_DS1302();
- while(1)
- {
- GetDateTime();
- disp_buff[2]=CurrDateTime[6]>>4;
- disp_buff[3]=CurrDateTime[6]&0x0F;
- disp_buff[4]=CurrDateTime[4]>>4;
- disp_buff[5]=CurrDateTime[4]&0x0F;
- disp_buff[6]=CurrDateTime[3]>>4;
- disp_buff[7]=CurrDateTime[3]&0x0F;
- disp_buff[8]=CurrDateTime[2]>>4;
- disp_buff[9]=CurrDateTime[2]&0x0F;
- disp_buff[10]=CurrDateTime[1]>>4;
- disp_buff[11]=CurrDateTime[1]&0x0F;
- disp_buff[12]=CurrDateTime[0]>>4;
- disp_buff[13]=CurrDateTime[0]&0x0F;
- disp_buff[14]=CurrDateTime[5]-1;
-
- for(i=15;i<18;i++)disp_buff[i]=12;
- Config_TC72();
- sprintf(t_buff,"%5.1f",Read_TC72_Temperature());
- i=j=0;len=strlen(t_buff);
- for(i=len-1;i!=0xFF;i--)
- {
- c=t_buff[i];if(c=='.')continue;
- if(c>='0'&&c<='9')disp_buff[18-j]=c-'0';
- else if (c=='-')disp_buff[18-j]=13;
- j++;
- }
-
- for(i=20;i!=0xFF;i--)
- {
- if(i!=17)Serial_Input_595(SEG_CODE[disp_buff[i]]);
- else Serial_Input_595(SEG_CODE[disp_buff[i]]&0x7F);
- }
-
- Parallel_Output_595();
-
- if(curr_second!=CurrDateTime[0])
- {
- curr_second=CurrDateTime[0];
- if(TR0==0)P0&=0xFC;TR0=1;
- }
- }
- }
- //-----------------------------------------------------------------
- // T0中断函数(控制秒闪烁,每隔500ms关闭LED,开LED由主程序控制)
- //-----------------------------------------------------------------
- void LED_Flash() interrupt 1
- {
- static INT8U T_Count=0;
- TH0=(INT16U)(-11.0592/12*50000)>>8;
- TL0=(INT16U)(-11.0592/12*50000)&0xFF;
- if(++T_Count==10)
- {
- P0|=0x03;T_Count=0;TR0=0;
- }
- }
复制代码//-----------------------------------------------------------------
// 名称: SPI接口温度传感器TC72驱动程序
//-----------------------------------------------------------------
#include "STC15xxx.h"
#include <intrins.h>
#include <stdio.h>
#include <math.h>
#define u8 unsigned char
#define u16 unsigned int
//TC72寄存器地址定义
#define TC72_CTRL 0x80 //控制寄存器
#define TC72_TEMP_LSB 0x01 //温度低字节
#define TC72_TEMP_MSB 0x02 //温度高字节
#define TC72_MANU_ID 0x03 //制造商ID
//SPI接口引脚定义(模拟方式)
sbit SCK = P3^4; //串行时钟控制脚
sbit CE = P3^5; //片选
sbit SDI = P3^6; //串行数据输入
sbit SDO = P3^7; //串行数据输出
u8 Temp_Value[2]; //两字节温度值原始数据
extern void delay_ms(u16 x);
//-----------------------------------------------------------------
// 从当前地址读取一字节数据(模拟方式)
//-----------------------------------------------------------------
u8 _ReadByte() {
u8 i ,d = 0x00;
for(i = 0; i < 8; i++) //串行读取8位数据
{ //SCK下降沿读取数据,读取的位保存到左移以后的d的低位
SCK = 1; SCK = 0; d = (d << 1) | SDO;
}
return d; //返回读取的字节
}
//-----------------------------------------------------------------
// 向当前地址写入一字节数据(模拟方式)
//-----------------------------------------------------------------
void _WriteByte(u8 dat) {
u8 i;
for(i = 0; i < 8; i++) { //串行写入8位数据
dat <<= 1; SDI = CY; //dat左移位,高位被移入CY,发送高位
SCK = 0; SCK = 1; //时钟上升沿向存储器写入数据
}
}
//-----------------------------------------------------------------
// 向TC72写入两字节(地址,数据)(模拟方式)
//-----------------------------------------------------------------
void Write_TC72(u8 addr, u8 dat) {
CE = 1; //SPI_EN();
_WriteByte(addr); //SPI_SendData(addr);
_WriteByte(dat); //SPI_SendData(dat);
CE = 0; //SPI_DI();
}
//-----------------------------------------------------------------
// 写TC72配置数据
//-----------------------------------------------------------------
void Config_TC72() {
Write_TC72(TC72_CTRL,0x15); //配置为单次转换与关断模式
}
//-----------------------------------------------------------------
// 从TC72读取两字节温度数据并转换为浮点温度值
//-----------------------------------------------------------------
float Read_TC72_Temperature() {
Config_TC72();
delay_ms(50);
CE = 1; //SPI_EN();
//发送读温度高字节命令
_WriteByte(TC72_TEMP_MSB); //SPI_SendData(TC72_TEMP_MSB);
//连续读取两字节(连续读取时先得到的是高字节,后得到的是低字节)
Temp_Value[1] = _ReadByte(); //SPI_SendData(0xFF);//读高字节
Temp_Value[0] = _ReadByte(); //SPI_SendData(0xFF);//读低字节
CE = 0; //SPI_DI();
//还可以使用以下单字节读取的方法
//SPI_EN();
//SPI_SendData(TC72_TEMP_LSB); //发送读温度低字节命令
//T[0] = SPI_SendData(0xFF); //读LSB
//SPI_DI();
//SPI_EN();
//SPI_SendData(TC72_TEMP_MSB); //发送读温度高字节命令
//T[1] = SPI_SendData(0xFF); //读MSB
//SPI_DI();
return (int)(((int)((Temp_Value[1]<<8)|Temp_Value[0]))>>6) * 0.25;
}
|