有帮助的话点个赞吧~
main.c
#include <STC15F2K60S2.H>
#include "iic.h"
#include "onewire.h"
typedef struct
{
unsigned char b1:1;
unsigned char b2:1;
unsigned char b3:1;
unsigned char b4:1;
unsigned char b5:1;
unsigned char b6:1;
unsigned char b7:1;
unsigned char b8:1;
}Bits;
typedef union
{
unsigned char Hex;
Bits B;
}HexToBit;
HexToBit led_ctrl;
unsigned char code smg_duanma[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsigned char smg[8];
bit lock_smg=0;
bit busy;
unsigned char rx_buf;
unsigned int pwm_cnt; //0.1s为间隔点亮
bit pwm_flag=0; //1就开始闪
unsigned char mode_smg=0;
void SendData(unsigned char dat);
void SendString(char *s);
void vDevice_Process(unsigned char p2dat,unsigned char p0dat)
{
P0 = p0dat;
P2 = (P2&0x1f)|p2dat;
P2 = P2&0x1f;
}
//定时器2
void Timer2Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x20; //设置定时初值
T2H = 0xD1; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
EA=1;
IE2 |= 0x04;
}
//波特率设置
void UartInit(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xC7; //设定定时初值
TH1 = 0xFE; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA=1;
ES=1;
}
//继电器控制
unsigned char BR_cont=0x00;
bit flag_RELAY=0;
unsigned int cnt_Relay;
void vRELAY_Process()
{
if(cnt_Relay>=500)
{
cnt_Relay=0;
if(flag_RELAY==1)
{
BR_cont=BR_cont|0x10;
vDevice_Process(0xa0, BR_cont);
}
else
{
BR_cont=BR_cont&0xef;
vDevice_Process(0xa0, BR_cont);
}
}
}
//蜂鸣器控制
bit flag_buzz=0;
unsigned int cnt_Buzz;
void vBuzz_Process()
{
if(cnt_Buzz>=500)
{
cnt_Buzz=0;
if(flag_buzz==1)
{
BR_cont=BR_cont|0x40;
vDevice_Process(0xa0, BR_cont);
}
else
{
BR_cont=BR_cont&0xbf;
vDevice_Process(0xa0, BR_cont);
}
}
}
//LED控制
void vLED_Process()
{
if(mode_smg==0)
{
led_ctrl.B.b1=0; //L1点亮
led_ctrl.B.b2=1; //L2熄灭
}
else if(mode_smg==1)
{
led_ctrl.B.b1=1; //L1熄灭
led_ctrl.B.b2=0; //L2点亮
}
vDevice_Process(0x80, led_ctrl.Hex);
}
//采集温度
unsigned int cnt_temp;
unsigned int temp;
void vRead_temperture()
{
if(cnt_temp>=500)
{
cnt_temp=0;
temp = vRead_temp()*10;//返回浮点数,乘10后转为整数就是三位数
if(temp>=280)
{
flag_RELAY=1;
}
else
{
flag_RELAY=0;
}
}
}
//采集RB2电压
unsigned int rb2_dat;
unsigned int cnt_rb2;
void vGet_rb2()
{
if(cnt_rb2>=100)
{
cnt_rb2=0;
rb2_dat = vRead_RB2();
if(rb2_dat>=360)
{
flag_buzz=1;
}
else
{
flag_buzz=0;
}
}
}
//数码管操作函数
void vSMG_Process()
{
if(mode_smg==0)
{
smg[0]=0xc1;
smg[1]=smg_duanma[1];
smg[2]=0xff;
smg[3]=0xff;
smg[4]=0xff;
smg[5]=smg_duanma[temp/100];
smg[6]=smg_duanma[temp/10%10]&0x7f;
smg[7]=smg_duanma[temp%10];
}
if(mode_smg==1)
{
smg[0]=0xc1;
smg[1]=smg_duanma[2];
smg[2]=0xff;
smg[3]=0xff;
smg[4]=0xff;
smg[5]=smg_duanma[rb2_dat/100]&0x7f;
smg[6]=smg_duanma[rb2_dat/10%10];
smg[7]=smg_duanma[rb2_dat%10];
}
}
//数码管显示
void vSMG_Show()
{
static unsigned char i;
vDevice_Process(0xc0, 0x00);
vDevice_Process(0xe0, smg[i]);
vDevice_Process(0xc0, 0x01<<i);
i=(i+1)%8;
}
//矩阵键盘扫描
unsigned char Scan_Keys()
{
unsigned char key_io=0xff;
P32=0;P33=0;
P34=1;P35=1;P42=1;P44=1;
if(P44==0) key_io=0x70;
if(P42==0) key_io=0xb0;
if(P35==0) key_io=0xd0;
if(P34==0) key_io=0xe0;
P32=1;P33=1;
P34=0;P35=0;P42=0;P44=0;
if(P33==0) key_io = key_io|0x07;
if(P32==0) key_io = key_io|0x0b;
return key_io;
}
//三行按键
unsigned char Trg,Cont;
void vThreeLine_Key()
{
unsigned char keyio;
unsigned char ReadData;
keyio = Scan_Keys();
ReadData = keyio^0xff;
Trg = ReadData&(ReadData^Cont);
Cont = ReadData;
}
//按键处理
unsigned int cnt_key;
void vKeys_Process()
{
if(cnt_key>=20)
{
cnt_key=0;
vThreeLine_Key();
if(Trg == 0x88)//S4
{
lock_smg=1; //打开锁 进入锁定状态
}
if(Trg == 0x84)//S5
{
if(lock_smg==1)
{
lock_smg=0;
led_ctrl.B.b3=1; //L3熄灭 解锁后要熄灭
}
}
if(Trg == 0x28)//S12
{
if(mode_smg==0)
{
SendString("TEMP:");
SendData(temp/100+'0');SendData(temp/10%10+'0');SendData('.');SendData(temp%10+'0');
SendData('C');
}
if(mode_smg==1)
{
SendString("Voltage:");
SendData(rb2_dat/100+'0');SendData('.');SendData(rb2_dat/10%10+'0');SendData(rb2_dat%10+'0');
SendData('V');
}
}
}
}
/*----------------------------
发送串口数据
----------------------------*/
void SendData(unsigned char dat)
{
while (busy); //等待前面的数据发送完成
busy = 1;
SBUF = dat; //写数据到UART数据寄存器
}
/*----------------------------
发送字符串
----------------------------*/
void SendString(char *s)
{
while (*s) //检测字符串结束标志
{
SendData(*s++); //发送当前字符
}
}
//串口接收处理函数
void vUartRx_Process()
{
if(lock_smg==0) //如果锁定关闭 才根据指令切换界面
{
if(rx_buf=='A') mode_smg=0; //发送A 进入温度显示
if(rx_buf=='B') mode_smg=1; //发送B 进入电压显示
}
rx_buf=0;
}
//系统初始化
void vSystem_Init()
{
led_ctrl.Hex=0xff;
vDevice_Process(0x80,0xff);
vDevice_Process(0xa0,0x00);
}
void main()
{
Timer2Init();
vSystem_Init();
UartInit();
SendString("hello");
while(1)
{
vSMG_Process();
vRead_temperture();
vGet_rb2();
vRELAY_Process();
vBuzz_Process();
vKeys_Process();
vUartRx_Process();
}
}
void Timer2() interrupt 12
{
cnt_temp++;cnt_rb2++;cnt_Relay++;cnt_Buzz++;cnt_key++;
vSMG_Show();
vLED_Process();
if(lock_smg==1)
{
pwm_cnt++;
if(pwm_cnt<100)
{
led_ctrl.B.b3=0; //L3点亮
}
else if(pwm_cnt<200)
{
led_ctrl.B.b3=1; //L3熄灭
}
else
{
pwm_cnt=0;
}
vDevice_Process(0x80, led_ctrl.Hex);
}
}
/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4
{
if (RI)
{
RI = 0; //清除RI位
SBUF=SBUF;
rx_buf=SBUF;
}
if (TI)
{
TI = 0; //清除TI位
busy = 0; //清忙标志
}
}
iic.c
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <reg52.h>
#include <intrins.h>
#define DELAY_TIME 5
sbit sda=P2^1;
sbit scl=P2^0;
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
//读取电压
unsigned int vRead_RB2()
{
unsigned char rb2;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
rb2 = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return rb2*100/51;
}
onewire.c
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <reg52.h>
sbit DQ=P1^4;
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
//获取温度
float vRead_temp()
{
unsigned char LSB,MSB;
float temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
temp = ((MSB<<8)|LSB)*0.0625;
return temp;
}