一、初始化外设
新建工程:
(1)主函数:
#ifndef MAIN_H
#define MAIN_H
#include "Public.h"
#endif
#include "main.h"
void main()
{
All_Close();
}
(2)公共函数:
#ifndef PUBLIC_H
#define PUBLIC_H
#include <STC15F2K60S2.H>
#define u8 unsigned char
#define u16 unsigned char
void All_Close();
#endif
#include "Public.h"
/*
选择锁存器,发送信息
*/
void Select(u8 cs,u8 s_data)
{
P0 = s_data;
P2 = P2 & 0x1f | (cs<<5);
P2 &= 0x1f;
}
/*
关闭无关设备
*/
void All_Close()
{
//关闭蜂鸣器和继电器
Select(5,0x00);
//关闭LED
Select(4,0xff);
//清空数码管位选
Select(7,0xff);
}
数码管,定时器0:
(1)主函数:
#include "main.h"
void SEG_Proc();
void main()
{
All_Close();
Timer0_Init();
while(1)
{
SEG_Proc();
}
}
void Timer0_Isr(void) interrupt 1
{
if(++seg_delay == 300)seg_delay = 0;
SEG_Show(COD[PSI],PSI);
if(++PSI == 8)PSI = 0;
}
void SEG_Proc()
{
if(seg_delay)return;
seg_delay = 1;
sprintf(COT,"P %2u %2u",(u16)30,(u16)20);
// sprintf(COT,"C %2u",(u16)24);
SEG_TSL(COT,COD);
}
(2)数码管:
#ifndef SEG_H
#define SEG_H
#include "Public.h"
void SEG_TSL(u8 *input,u8 *output);
void SEG_Show(u8 COD,u8 PSI);
#endif
#include "SEG.h"
code unsigned char Seg_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e //F
};
/*
输入字符串,输出数码管代码
*/
void SEG_TSL(u8 *input,u8 *output)
{
u8 i=0;
for(i=0;i<8;i++)
{
switch(input[i])
{
case '0':output[i] = Seg_Table[0];break;
case '1':output[i] = Seg_Table[1];break;
case '2':output[i] = Seg_Table[2];break;
case '3':output[i] = Seg_Table[3];break;
case '4':output[i] = Seg_Table[4];break;
case '5':output[i] = Seg_Table[5];break;
case '6':output[i] = Seg_Table[6];break;
case '7':output[i] = Seg_Table[7];break;
case '8':output[i] = Seg_Table[8];break;
case '9':output[i] = Seg_Table[9];break;
case 'C':output[i] = Seg_Table[12];break;
case 'P':output[i] = ~0x73;break;
default:output[i] = 0xff;
}
}
}
/*
数码管显示函数
*/
void SEG_Show(u8 COD,u8 PSI)
{
//消隐
Select(7,0xff);
//位选
Select(6,0x01<<PSI);
//段选
Select(7,COD);
}
(3)定时器:
#ifndef SIMPLE_H
#define SIMPLE_H
#include "Public.h"
void Timer0_Init(void);
#endif
#include "Simple.h"
void Timer0_Init(void) //1毫秒@12MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初始值
TH0 = 0xD1; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
}
独立按键:
(1)部分主函数:
#include "main.h"
void SEG_Proc();
void Key_Proc();
void main()
{
All_Close();
Timer0_Init();
while(1)
{
// SEG_Proc();
Key_Proc();
}
}
void Timer0_Isr(void) interrupt 1
{
if(++seg_delay == 300)seg_delay = 0;
if(++key_dealy == 10)key_dealy = 0;
SEG_Show(COD[PSI],PSI);
if(++PSI == 8)PSI = 0;
}
void Key_Proc()
{
static u8 key_old;
u8 key_now=0,key_down=0;
if(key_dealy)return;
key_dealy = 1;
key_now = D_Key();
key_down = key_now & (key_now ^ key_old);
key_old = key_now;
if(key_down)
{
sprintf(COT,"%u",(u16)key_down);
SEG_TSL(COT,COD);
}
}
(2)按键检测函数:
/*
独立按键按键检测
*/
u8 D_Key()
{
u8 i=0;
for(;i<4;i++)
if((P3 & (0x08>>i)) == 0)
return i+4;
return 0;
}
LED:
(1)部分主函数:
void Timer0_Isr(void) interrupt 1
{
if(++seg_delay == 300)seg_delay = 0;
if(++key_dealy == 10)key_dealy = 0;
SEG_Show(COD[PSI],PSI);
if(++PSI == 8)PSI = 0;
LED_Show(l_data);
}
void Key_Proc()
{
static u8 key_old;
u8 key_now=0,key_down=0;
if(key_dealy)return;
key_dealy = 1;
key_now = D_Key();
key_down = key_now & (key_now ^ key_old);
key_old = key_now;
if(key_down)
{
l_data = 0x01<<(key_down-4);
}
}
(2)LED显示函数:
/*
输入8位数据点亮LED灯,1为亮
*/
void LED_Show(u8 l_data)
{
Select(4,~l_data);
}
PCF8591:
(1)部分主函数:
void SEG_Proc()
{
if(seg_delay)return;
seg_delay = 1;
//改变输出电压
PCF8591_DAC(3);
sprintf(COT,"P %2u %2u",(u16)30,(u16)20);
// sprintf(COT,"C %2u",(u16)24);
SEG_TSL(COT,COD);
}
(2)PCF8591:
/*
DAC输出电压
*/
void PCF8591_DAC(u8 volt)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_SendByte(volt*255/5);
IIC_WaitAck();
IIC_Stop();
}
DS18B20:
(1)部分主函数:
void main()
{
All_Close();
Timer0_Init();
while(1)
{
SEG_Proc();
DS18B20_Proc();
Key_Proc();
}
}
void SEG_Proc()
{
if(seg_delay)return;
seg_delay = 1;
//改变输出电压
PCF8591_DAC(3);
// sprintf(COT,"P %2u %2u",(u16)30,(u16)20);
sprintf(COT,"C %2u",(u16)ds_data);
SEG_TSL(COT,COD);
}
void DS18B20_Proc()
{
if(ds_delay)return;
ds_delay = 1;
ds_data = DS18B20_Read()>>4;
}
(2)DS18B20:
/*
利用DS18B20检测温度
*/
u16 DS18B20_Read()
{
u8 LSB,MSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
return (MSB<<8) | LSB;
}
二、实现功能:
基本框架:
数码管显示有两种模式:数据显示模式,参数设置模式
参数设置模式又分为上限设置模式和下限设置模式
(1)部分主函数:
void SEG_Proc()
{
if(seg_delay)return;
seg_delay = 1;
//改变输出电压
PCF8591_DAC(3);
if(seg_mode)
sprintf(COT,"P %2u %2u",(u16)temper[1],(u16)temper[0]);
else
sprintf(COT,"C %2u",(u16)ds_data);
SEG_TSL(COT,COD);
}
void Key_Proc()
{
static u8 key_old;
u8 key_now=0,key_down=0;
if(key_delay)return;
key_delay = 1;
key_now = D_Key();
key_down = key_now & (key_now ^ key_old);
key_old = key_now;
if(seg_mode)
{
switch(key_down)
{
case 4:seg_mode ^= 1;break;
case 5:set_mode ^= 1;break;
case 6:
temper[set_mode]++;
if(temper[set_mode]>=100) temper[set_mode] = 0;//防止数据越界
break;
case 7:
temper[set_mode]--;
if(temper[set_mode]>100) temper[set_mode] = 99;
break;
}
}
else
if(key_down == 4)
{
seg_mode ^= 1;
set_mode = 0;
}
}
参考代码:
(1)主函数:
#ifndef MAIN_H
#define MAIN_H
#include "Public.h"
#include "SEG.h"
#include "Simple.h"
#include "stdio.h"
//模式定义
u8 seg_mode;// 0为显示模式,1为设置模式
u8 set_mode;// 0为下限,1为上限
//设置模式
u8 temper[2];//0为下限,1为上限
u8 temp[2];
u8 error;
//定时器
u8 key_delay;
u16 seg_delay,ds_delay;
u16 count_ms;
//数码管
u8 COT[9],COD[8],PSI;
//LED
u8 l_data;
//DS18B20
u16 ds_data;
#endif
#include "main.h"
void SEG_Proc();
void Key_Proc();
void DS18B20_Proc();
void Init();
void main()
{
All_Close();
Timer0_Init();
Init();
while(1)
{
SEG_Proc();
DS18B20_Proc();
Key_Proc();
}
}
void Timer0_Isr(void) interrupt 1
{
if(++seg_delay == 300)seg_delay = 0;
if(++key_delay == 10)key_delay = 0;
if(++ds_delay == 500)ds_delay = 0;
SEG_Show(COD[PSI],PSI);
if(++PSI == 8)PSI = 0;
LED_Show(l_data);
}
void SEG_Proc()
{
if(seg_delay)return;
seg_delay = 1;
//改变输出电压
if(ds_data < temper[0])
PCF8591_DAC(2);
else if(ds_data < temper[1])
PCF8591_DAC(3);
else
PCF8591_DAC(4);
if(seg_mode)
sprintf(COT,"P %2u %2u",(u16)temp[1],(u16)temp[0]);
else
sprintf(COT,"C %2u",(u16)ds_data);
SEG_TSL(COT,COD);
}
void Key_Proc()
{
static u8 key_old;
u8 key_now=0,key_down=0;
if(key_delay)return;
key_delay = 1;
key_now = D_Key();
key_down = key_now & (key_now ^ key_old);
key_old = key_now;
if(seg_mode)
{
switch(key_down)
{
case 4:
seg_mode ^= 1;
if(temp[0]<temp[1])
{
temper[0] = temp[0];
temper[1] = temp[1];
error = 0;
}
else
error = 1;
break;
case 5:set_mode ^= 1;break;
case 6:
temp[set_mode]++;
if(temp[set_mode]>=100) temp[set_mode] = 0;//防止数据越界
break;
case 7:
temp[set_mode]--;
if(temp[set_mode]>100) temp[set_mode] = 99;
break;
}
}
else
if(key_down == 4)
{
seg_mode ^= 1;
set_mode = 0;
temp[0] = temper[0];
temp[1] = temper[1];
}
}
void DS18B20_Proc()
{
if(ds_delay)return;
ds_delay = 1;
ds_data = DS18B20_Read()>>4;
//指示灯
if(error)
l_data = 0x01<<3;
else if(ds_data < temper[0])
l_data = 0x01<<2;
else if(ds_data < temper[1])
l_data = 0x01<<1;
else
l_data = 0x01;
}
void Init()
{
temper[0] = 20;
temper[1] = 30;
seg_mode = 0;
}
(2)公共函数:
#ifndef PUBLIC_H
#define PUBLIC_H
#include <STC15F2K60S2.H>
#define u8 unsigned char
#define u16 unsigned int
void All_Close();
void Select(u8 cs,u8 s_data);
#endif
#include "Public.h"
/*
选择锁存器,发送信息
*/
void Select(u8 cs,u8 s_data)
{
P0 = s_data;
P2 = P2 & 0x1f | (cs<<5);
P2 &= 0x1f;
}
/*
关闭无关设备
*/
void All_Close()
{
//关闭蜂鸣器和继电器
Select(5,0x00);
//关闭LED
Select(4,0xff);
//清空数码管位选
Select(7,0xff);
}
(3)数码管:
#ifndef SEG_H
#define SEG_H
#include "Public.h"
void SEG_TSL(u8 *input,u8 *output);
void SEG_Show(u8 COD,u8 PSI);
#endif
#include "SEG.h"
code unsigned char Seg_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e //F
};
/*
输入字符串,输出数码管代码
*/
void SEG_TSL(u8 *input,u8 *output)
{
u8 i=0;
for(i=0;i<8;i++)
{
switch(input[i])
{
case '0':output[i] = Seg_Table[0];break;
case '1':output[i] = Seg_Table[1];break;
case '2':output[i] = Seg_Table[2];break;
case '3':output[i] = Seg_Table[3];break;
case '4':output[i] = Seg_Table[4];break;
case '5':output[i] = Seg_Table[5];break;
case '6':output[i] = Seg_Table[6];break;
case '7':output[i] = Seg_Table[7];break;
case '8':output[i] = Seg_Table[8];break;
case '9':output[i] = Seg_Table[9];break;
case 'C':output[i] = Seg_Table[12];break;
case 'P':output[i] = ~0x73;break;
default:output[i] = 0xff;
}
}
}
/*
数码管显示函数
*/
void SEG_Show(u8 COD,u8 PSI)
{
//消隐
Select(7,0xff);
//位选
Select(6,0x01<<PSI);
//段选
Select(7,COD);
}
(4)其他外设:
#ifndef SIMPLE_H
#define SIMPLE_H
#include "Public.h"
#include "iic.h"
#include "onewire.h"
void Timer0_Init(void);
u8 D_Key();
void LED_Show(u8 l_data);
void PCF8591_DAC(u8 volt);
u16 DS18B20_Read();
#endif
#include "Simple.h"
void Timer0_Init(void) //1毫秒@12MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初始值
TH0 = 0xD1; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
}
/*
独立按键按键检测
*/
u8 D_Key()
{
u8 i=0;
for(;i<4;i++)
if((P3 & (0x08>>i)) == 0)
return i+4;
return 0;
}
/*
输入8位数据点亮LED灯,1为亮
*/
void LED_Show(u8 l_data)
{
Select(4,~l_data);
}
/*
DAC输出电压
*/
void PCF8591_DAC(u8 volt)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_SendByte(volt*255/5);
IIC_WaitAck();
IIC_Stop();
}
/*
利用DS18B20检测温度
*/
u16 DS18B20_Read()
{
u8 LSB,MSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
return (MSB<<8) | LSB;
}