河南省一,客观题做得不太好,程序题实现很好
原试题链接
源码
刚开始用的是矩阵按键,后来才发现是独立按键,有部分注释没有更改
ii.c
#include "reg52.h"
#include "intrins.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
发送应答
//void IIC_SendAck(bit ackbit)
//{
// SCL = 0;
// SDA = ackbit; // 0:应答,1:非应答
// IIC_Delay(DELAY_TIME);
// SCL = 1;
// IIC_Delay(DELAY_TIME);
// SCL = 0;
// SDA = 1;
// IIC_Delay(DELAY_TIME);
//}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
//unsigned char IIC_RecByte(void)
//{
// unsigned char i, da;
// for(i=0; i<8; i++)
// {
// SCL = 1;
// IIC_Delay(DELAY_TIME);
// da <<= 1;
// if(SDA) da |= 1;
// SCL = 0;
// IIC_Delay(DELAY_TIME);
// }
// return da;
//}
void write_dac(unsigned char add)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
}
onewire.c
#include "reg52.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
unsigned int i = 12;
while(t--)
{
for(i=0;i<12;i++);
}
}
//通过单总线向DS18B20写一个字节
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);
}
//从DS18B20读取一个字节
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;
}
//DS18B20设备初始化
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;
}
unsigned char read_temperature(void)
{
unsigned int temp;
unsigned char low,high;
init_ds18b20();
Delay_OneWire(1);
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
init_ds18b20();
Delay_OneWire(1);
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
low = Read_DS18B20();
high = Read_DS18B20();
temp = high;
temp <<=4;
temp |= (low>>4);
return temp;
}
main.c
#include "STC15.h"
#include "iic.h"
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int
uchar code SMG_Duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x39,0x73};//11C 12P
uint code SMG_Com[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //数码管位选
uchar temp_table[8]={10,10,10,10,10,10,10,10};//初始化温度显示数组,默认不显示
uchar set_table[8]={10,10,10,10,10,10,10,10};//初始化参数设置数组,默认不显示
static uint temp = 0; //默认温度为0
static char temp_max = 30;//默认上限温度为30℃
static char temp_min = 20;//默认下限温度为20℃
static uchar menu = 0; //默认界面为数据显示界面
static char temp_max_prev = 30;//默认合理的上限温度为30℃
static char temp_min_prev = 20;//默认合理的下限温度为20℃
bit temp_set_flag = 0; //定义参数切换按键标志
bit key_flag = 0; //定义10ms扫描按键标志
bit led_flag = 1; //定义温度合理时LED可亮标志
#define KEY P3
uchar trg = 0;
uchar cont = 0;
//按键扫描函数
void KeyScan(void)
{
uchar KeyData = KEY ^ 0xff;
trg = KeyData & (KeyData ^ cont);
cont = KeyData;
}
//定时器0初始化函数
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
//控制DAC输出函数
void dac_ctrl(void)
{
if((temp!=85) && led_flag)
{
if(temp > temp_max) //温度大于上限温度,输出4V
{
write_dac((4+0.04)*255/5);
P2 = 0x80;P0 = 0xfe;P2 = 0x00;
}
if((temp >= temp_min) && (temp <= temp_max))//温度介于上限温度和下限温度,输出3V
{
write_dac((3+0.04)*255/5);
P2 = 0x80;P0 = 0xfd;P2 = 0x00;
}
if(temp < temp_min) //温度小于下限温度,输出2V
{
write_dac((2+0.04)*255/5);
P2 = 0x80;P0 = 0xfb;P2 = 0x00;
}
}
}
//控制数组显示函数
void table_ctrl(void)
{
if(temp!=85) //当温度显示为非85℃时,显示数组,否则显示默认值
{
temp_table[0] = 11;
temp_table[1] = 10;
temp_table[2] = 10;
temp_table[3] = 10;
temp_table[4] = 10;
temp_table[5] = 10;
temp_table[6] = temp/10;
temp_table[7] = temp%10;
}
//参数设置数组
set_table[0] = 12;
set_table[1] = 10;
set_table[2] = 10;
set_table[3] = temp_max/10;
set_table[4] = temp_max%10;
set_table[5] = 10;
set_table[6] = temp_min/10;
set_table[7] = temp_min%10;
}
//控制显示界面函数
void menu_ctrl(void)
{
if(key_flag)//10ms进行按键扫描、温度读取、显示界面切换
{
key_flag = 0; //清除标志
KeyScan(); //按键扫描
temp = read_temperature();//读取温度值
if(trg & 0x08) //S4进行界面切换
{
menu++;
temp_set_flag = 0;//清除参数设置标志
if(menu == 1) //判断显示参数界面时,上限温度和下限温度是否合理
{
if(temp_max < temp_min)//不合理时,将上限温度和下限温度恢复为上一次的合理值
{
temp_max = temp_max_prev;
temp_min = temp_min_prev;
menu = 0; //显示温度数据界面
}
}
if(menu == 2) //界面切换
menu = 0;
}
if(menu == 1) //处于参数设置界面事S5、S6、S7按键有效
{
if(trg & 0x04) //S5控制上限温度和下限温度参数切换
{
temp_set_flag = !temp_set_flag;
}
if(trg & 0x02) //S6控制上限温度或下限温度的增加
{
if(temp_set_flag)
{
temp_max ++;
if(temp_max == 100) //设置参数范围
temp_max = 99;
}
else
{
temp_min ++;
if(temp_min == 100) //设置参数范围
temp_min = 99;
}
}
if(trg & 0x01) //S7控制上限温度或下限温度的减少
{
if(temp_set_flag)
{
temp_max --;
if(temp_max == -1) //设置参数范围
temp_max = 0;
}
else
{
temp_min --;
if(temp_min == -1) //设置参数范围
temp_min = 0;
}
}
}
if(temp_max >= temp_min) //当上限温度和下限温度合理时,将其值保存到合理的上限、下限温度
{
temp_max_prev = temp_max;
temp_min_prev = temp_min;
led_flag = 1; //温度参数合理时LED可亮标志
}
else
{
P2 = 0x80;P0 = 0xf7;P2 = 0x00; //温度不合理时,L4亮
led_flag = 0; //温度参数合理LED可亮标志清0
}
}
}
void main(void)
{
Timer0Init(); //定时器初始化
P2 = 0xa0;P0 = 0x00;P2 = 0x00; //默认蜂鸣器、继电器关闭
P2 = 0x80;P0 = 0xff;P2 = 0x00; //默认LED关闭
temp = read_temperature(); //读取DS18B20第一次温度(85℃)
while(1)
{
menu_ctrl();
table_ctrl();
dac_ctrl();
}
}
void Timer0()interrupt 1
{
static int smg_count = 0,key_count =0,i = 0;
if(smg_count++ == 1)
{
smg_count = 0;
P2 = 0xc0;P0 = 0x00;P2 = 0x00;//消影
if(menu == 0)
{
P2 = 0xe0;P0 = ~SMG_Duan[temp_table[i]];P2 = 0x00; //显示温度数据
}
if(menu == 1)
{
P2 = 0xe0;P0 = ~SMG_Duan[set_table[i]];P2 = 0x00; //显示参数设置
}
P2 = 0xc0;P0 = SMG_Com[i];P2 = 0x00;
i++;
if(i == 8)
i = 0;
}
if(key_count++ ==10) //定时10ms
{
key_count = 0;
key_flag = 1;
}
}
错误不妥之处,欢迎批评指正。