本帖最后由 brew9 于 2020-2-27 14:40 编辑
这里分享一个基于开发板的简温度记录系统,所有模块均为板载。
以下为实物等图片:
- /*
- 这是一个基于开发板的简易的温度记录系统,所有模块均为板载。
-
- 用数码管显示温度和时间;
- 用时钟模块提供时基;
- 用24C02保存温度数据;
- 用蜂鸣器做操作提示;
- 用串口输出数据到电脑。
- Key_1启动温度记录,Key_2输出温度数据。
- 注:如果没有时钟模块也可以用单片机定时器计时,不过计时精度要差很多。
- */
- #include "config.h"
- #include "timer.h"
- #include "ds18b20.h"
- #include "ds1302.h"
- #include "i2c.h"
- uint8 timer; //定时器计数
- uint8 n = 0; //24c02内存位置变量
- int16 temp; //温度变量
- //共阴数码管0-9编码和位码
- uchar code seg_tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
- uchar code bit_tab[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
- //用于保存数字对应数码管编码的数组
- uchar num_code[8] = {0};
- //启动记录和改变延时的位变量
- bit starting,bF;
- //保存当前时间的结构体
- struct sTime cTime;
- //串口通讯初始化
- void T_U_init()
- {
- PCON = 0; //正常波特率(不翻倍)
- TMOD = 0X21; //T0工作方式1,T1工作方式2
- TH0 = 0xdc;
- TL0 = 0x00; //T0初值,10ms溢出
- TH1 = 0xfd;
- TL1 = 0xfd; //设置波特率9600
- IE = 0x82; //打开总中断、T0中断。禁止T1、串口中断
- SCON = 0x40; //串口工作方式1
- TCON = 0x50; //启动定时器0、1
- }
- //拆分浮点数到num_code数组
- void float2code(float fnum)
- {
- uint8 i = 0;
- uint8 len, point_pos;
- uchar str[8];
- TI = 1;
- sprintf(str, "%.1f", fnum*0.0625);
- TI = 0;
- len = strlen(str);
- if (len>8) return;
- point_pos = len - 2;
-
- //拆分整数部分
- for (i=0; i<point_pos; i++)
- {
- if (i < (point_pos-1)){
- if (str[i]=='-'){
- num_code[i] = 0x40;
- }else{
- num_code[i] = seg_tab[str[i]-0x30];
- }
- }else{
- //小数点左边的数加上小数点编码
- num_code[i] = seg_tab[str[i]-0x30] + 0x80;
- }
- }
- //拆分小数部分
- for (i=point_pos; i<len-1; i++)
- {
- num_code[i] = seg_tab[str[i+1]-0x30];
- }
- }
- //刷新温度
- void ref_temp()
- {
- static int16 backup = 0;
-
- DS18B20_get_temp(&temp); //获取当前温度值
- DS18B20_start(); //启动下一次转换
-
- //温度无改变则不处理,减少计算量
- if (backup!=temp)
- {
- float2code(temp); //刷新上次温度值
- backup = temp;
- }
- }
- //刷新时间
- void ref_time()
- {
- DS1302_get_time(&cTime);
- //获取时间后把数据拆分到显示数组中
- num_code[4] = seg_tab[BCD2Dat(cTime.min) / 10];
- num_code[5] = seg_tab[BCD2Dat(cTime.min) % 10];
- num_code[6] = seg_tab[BCD2Dat(cTime.sec) / 10];
- num_code[7] = seg_tab[BCD2Dat(cTime.sec) % 10];
- }
- //8位数码管显示函数
- void display()
- {
- uint8 j = 0;
- for (j=0; j<8; j++)
- {
- bit_sel = 1;
- DATA = bit_tab[j];
- bit_sel = 0;
- seg_sel = 1;
- DATA = num_code[j];
- delay_ms(1);
- DATA = 0x00;
- seg_sel = 0;
- }
- }
- //保存当前温度
- void save_temp(int16 t,uint16 n)
- {
- bit isACK1,isACK2;
- uint8 tmp;
- //将16位温度数据拆分为低8位和高8位,写入24c02中
- tmp = t;
- isACK1 = AT24C02_write_byte(n, tmp);
- delay_ms(50);
- tmp = t>>8;
- isACK2 = AT24C02_write_byte(n+1, tmp);
-
- //记录成功则喇叭响一下
- if (isACK1 && isACK2)
- {
- beep = 0;
- delay_ms(10);
- beep = 1;
- }
- }
- //串口输出保存的温度
- void sent_temp()
- {
- uchar tmp,str[6];
- uint16 j;
- int16 t;
- for(j=0; j<255; j=j+2)
- {
- tmp = AT24C02_read_byte(j+1);
-
- //初发读取24c02加大延时,之后减少延时加快处理速度
- //如果不进行此处理,则可能发生数据丢失
- if(bF)
- {
- delay_ms(10);
- }else{
- delay_ms(1000);
- bF=1;
- }
-
- //重组16位温度int数据
- t = tmp << 8;
- tmp = AT24C02_read_byte(j);
- delay_ms(10);
- t |= tmp;
- //数据转换及串口输出
- TI = 1;
- sprintf(str, "%.2f", t*0.0625);
- printf("%s \n",str);
- while(!TI);
- TI = 0;
- }
- }
- void main()
- {
- uchar s,ts=1; //ts用于保存当前秒数,且必须赋值一个不等于0的值
-
- T_U_init();
- while(1)
- {
- display();
- //检测时基数据,定时记录温度
- if(starting)
- {
- s = BCD2Dat(cTime.sec);
- //只有当秒数变化时才进入判断步骤
- //此处每2秒记录一次(可加入ds1302的分钟数据加大间隔时间)
- if(s % 2 == 0 && s != ts)
- {
- save_temp(temp,n);
- n=n+2;
-
- //n初值为0,第一次记录数据后不再为0,所以不会进入结束。
- //当n=254时,记录最后一次数据,再加2后n为0,结束。
- if(n == 0)
- {
- starting = 0;
- beep = 0;
- delay_ms(10);
- beep = 1;
- }
- }
- ts = s;
- }
-
- //按键设置
- if (KEY_1==0)
- {
- delay_ms(10);
- if (KEY_1==0)
- {
- //初始化1302时把其分和秒对应内存清零
- DS1302_init();
- starting = 1;
- }
- while(!KEY_1);
- }
- if (KEY_2==0)
- {
- delay_ms(10);
- if (KEY_2==0)
- {
- sent_temp();
- }
- while(!KEY_2);
- }
- }
- }
- void timer0_service(void) interrupt 1
- {
- TH0 = 0xdc;
- TL0 = 0x00;
- timer++;
- if (timer == 100)
- {
- timer = 0;
- ref_temp();
- ref_time();
- }
- }
复制代码
|