LQB十二届手打代码

时间:2022-08-09 01:02:05


main.c

//生成和引用头文件
#include "stc15.h"
#include "stdio.h"//sprintf函数
#include "iic.h"//sprintf函数
#include "onewire.h"//sprintf函数

//写下程序框架,定时器1作为系统的定时时钟,1ms中断

typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;


/************* 本地常量声明 **************/
u8 code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码


u8 LEDbuf=0x00;
u8 ULNbuf=0x00;
u8 SMGtemp[20];
u8 SMGbuf[8];

#define LED 4
#define ULN 5
#define COM 6
#define ABC 7

//函数声明
void Delay1ms(); //@12.000MHz
void delayms(u16 tms);
void se(u8 x);//选择573
void init();//关闭所有外部设备
void LEDout(); //LED输出
void LEDctrl(); //LED数据刷新,100ms刷新一次,根据不同模式等变化
void ULNout(); //ULN输出
void ULNctrl(); //ULN数据刷新,100ms刷新一次,根据不同模式等变化
void SMGconv(); //数码管转换函数,将字符串转为打印的字段
void SMGnow(); //刷新页面的内容,更新当前的页面,300ms刷新一次页面,根据模式和页面指针
void SMGdisp();//数码管扫描函数,1ms刷新一次;

void KeyRead(); //按键函数
void ReadOut();//读取温度,等控制外设,500ms一次
//添加一下外设的头文件,文件等

//其他全局变量
u8 LEDtime=0; //LED时间0-200ms,所以u8类型合适了。
u8 ULNtime=0; //ULNtime时间0-200ms,所以u8类型合适了。
u16 SMGtime=0; //300ms,大于u8类型
u16 Readtime=0;

//三个页面
u8 page=0; //0是温度显示页面,1是参数显示页面,2是DAC输出页面

//温度参数
float wendu=24.25;//实时温度参数
float wenduset=25;//温度设置参数


//dac数据
float dac=3.25;

//模式指针
u8 mode=1;//等于1,是模式1,=2是模式2

//
//测试一下数码管程序对不对能不能显示正常
//从stc-isp软件复制定时器的配置过来
//-----------------------------------------------

#define FOSC 11059200L
#define T1MS (65536-FOSC/1000) //1T模式
//#define T1MS (65536-FOSC/12/1000) //12T模式
//-----------------------------------------------

/* Timer1 interrupt routine */
void tm1_isr() interrupt 3 using 1
{
LEDtime++;
ULNtime++;
SMGtime++;
Readtime++;

SMGdisp(); //1ms刷新一位数码管,一直打开
}
void main()
{
u8 i=5;

init();//关闭所有外设

read18b20();//添加头文件
delayms(800);
//AUXR,这个寄存器要熟悉,可能后面用到定时器0也需要配置一下
AUXR |= 0x40; //定时器1为1T模式
//TMOD,这个寄存器要熟悉,可能后面用到定时器0也需要配置一下
TMOD = 0x00; //设置定时器为模式0(16位自动重装载)
TL1 = T1MS; //初始化计时值
TH1 = T1MS >> 8;
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器0中断
EA = 1;
read18b20();//添加头文件

while(1)
{
if(LEDtime>100)
{
LEDtime=0;
LEDctrl();
}

if(SMGtime>300)
{
SMGtime=0;
SMGnow();
}

if(Readtime>500) //DAC输出,读取温度等,都在这个时间段里面
{
Readtime=0;
ReadOut();
}
KeyRead(); //按键函数

}
}


void KeyRead()
{
//题目要求,S4,S8 S9 S5
P32=0;P33=1;
P34=1;P35=1;P42=1;P44=1;
if(P44==0)
{
delayms(10);
if(P44==0) //S5 切换模式
{
if(mode==1)mode=2;
else if(mode==2)mode=1;
}
while(P44==0);//如果不放松的话,一直按着
}

else if(P42==0)
{
delayms(10);
if(P42==0) //S9
{
if(page==1)
{
wenduset=wenduset+1;
if(wenduset>99)wenduset=99;//最大加到99
}
}
while(P42==0);//如果不放松的话,一直按着
}

//题目要求,S4
P32=1;P33=0;
P34=1;P35=1;P42=1;P44=1;
if(P44==0)
{
delayms(10);
if(P44==0) //S4 切换页面
{
if(page==0)page=1;
else if(page==1)page=2;
else if(page==2)page=0;
}
while(P44==0);//如果不放松的话,一直按着
}

else if(P42==0)
{
delayms(10);
if(P42==0) //S8 参数界面下,温度减一
{
if(page==1)
{
wenduset=wenduset-1;
if(wenduset<10)wenduset=10;//最小减到10
}
}
while(P42==0);//如果不放松的话,一直按着
}


}
//******************************************函数定义Delay1ms()
void Delay1ms() //@12.000MHz
{
unsigned char i, j;

i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
//******************************************函数定义delayms(u16 tms)
void delayms(u16 tms)
{
u16 i;
for(i=0;i<tms;i++)
{
Delay1ms();
}

}
void se(u8 x)
{
switch(x)
{
case 0:P2=P2&0x1F;break;
case LED:P2=P2&0x1F|0x80;break;
case ULN:P2=P2&0x1F|0xA0;break;
case COM:P2=P2&0x1F|0xC0;break;
case ABC:P2=P2&0x1F|0xE0;break;
}
}

void init()//关闭所有外部设备
{
//关闭LED等,等
se(LED);LEDbuf=0x00;P0=~LEDbuf;se(0); //这里取反,记得,低电平点亮,这里取反等于高电平,熄灭
se(ULN);ULNbuf=0x00;P0=ULNbuf;se(0);//这里不取反,因为ULN本身是个反相器,原理图里面,高电平没作用
se(COM);P0=0xFF;se(0); //关闭数码管
se(ABC);P0=0x00;se(0);
}

void LEDout() //LED输出
{
se(LED);P0=~LEDbuf;se(0);
}
void LEDctrl() //LED数据刷新,100ms刷新一次,根据不同模式等变化
{
if(mode==1)
{
//L1点亮,否则熄灭 //bit0=1,
LEDbuf =LEDbuf |0x01;
}
else if(mode==2)
{
//L1点亮,否则熄灭 //bit0=0,
LEDbuf =LEDbuf &(~0x01);
}

if(page==0)
{
//L1点亮,否则熄灭 //bit1=1,
LEDbuf =LEDbuf |0x02; //0010
LEDbuf =LEDbuf &(~0x04); //0000
LEDbuf =LEDbuf &(~0x08); //0000
}
else if(page==1)
{
//L1点亮,否则熄灭 //bit1=1,
LEDbuf =LEDbuf |0x04; //0100
LEDbuf =LEDbuf &(~0x02); //0000
LEDbuf =LEDbuf &(~0x08); //0000
}
else if(page==2)
{
//L1点亮,否则熄灭 //bit1=1,
LEDbuf =LEDbuf |0x08; //0100
LEDbuf =LEDbuf &(~0x02); //0000
LEDbuf =LEDbuf &(~0x04); //0000
}

LEDout();//输出数据
}

void ReadOut()//读取温度,等控制外设,500ms一次
{
wendu=read18b20();
if(mode==1)
{
if(wendu<wenduset)
{
dac=0;
writeDAC(0);
}
else if(wendu>=wenduset)
{
dac=5;
writeDAC(255);
}
}
else if(mode==2)
{
dac=0.15*wendu-2;
writeDAC((int)(dac*51));
}
}
















void ULNout() //ULN输出
{
se(ULN);P0=ULNbuf;se(0);
}
void ULNctrl() //ULN数据刷新,100ms刷新一次,根据不同模式等变化
{

}
void SMGconv() //数码管转换函数,将字符串转为打印的字段
{
//数码管转换函数,注意小数点
u8 i,j,temp;
while(SMGtemp[i]!=0) //没有转换结束的话,就一个个转换到对应段码
{
switch(SMGtemp[i])
{
case '0':temp=0x3F;break;//注意,是单引号
case '1':temp=0x06;break;
case '2':temp=t_display[2];break;//一样的作用
case '3':temp=t_display[3];break;//一样的作用
case '4':temp=t_display[4];break;//一样的作用
case '5':temp=t_display[5];break;//一样的作用
case '6':temp=t_display[6];break;//一样的作用
case '7':temp=t_display[7];break;//一样的作用
case '8':temp=t_display[8];break;//一样的作用
case '9':temp=t_display[9];break;//一样的作用
//其他字符
case 'C':temp=0x39;break;
case 'P':temp=0x73;break;
case 'A':temp=0x77;break;
//***********
default:temp=0x00;break;
}
//判断下一个是不是小数点
if(SMGtemp[i+1]=='.')
{
temp =temp|0x80;
i=i+2;
}
else
{
i=i+1;
}

SMGbuf[j]=temp;
j=j+1;
}
}

//刷新页面的内容,更新当前的页面,300ms刷新一次页面
//,根据模式和页面指针
void SMGnow()
{
if(page==0)
{
//Cxxx25.24
sprintf(SMGtemp,"Cxxx%5.2f",wendu);//24.25有5个字符,2个小数点
}
else if(page==1)
{
sprintf(SMGtemp,"Pxxxxx%2d",(int)wenduset);//24.25有5个字符,2个小数点
}
else if(page==2)
{
sprintf(SMGtemp,"Axxxx%3.2f",dac);//24.25有5个字符,2个小数点
}

SMGconv();//转换段码

}
void SMGdisp()//数码管扫描函数,1ms刷新一次;
{
static u8 i=0;
se(COM);P0=0xFF;se(0); //关闭数码管
se(ABC);P0=0x00;se(0);

se(COM);P0=T_COM[i];se(0); //关闭数码管
se(ABC);P0=~SMGbuf[i];se(0);//记得取反

i=i+1;
if(i>=8)i=0;
}

iic.c

/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/

#include "stc15.h"
#include "intrins.h"
#include "iic.h"

#define DELAY_TIME 60 //stc15运算速度更加快

#define SlaveAddrW 0xA0 //这个是at24C02de
#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;
}
//输出DAC,时序,我忘记了,怎么办。参考stcISP
void writeDAC(unsigned char temp)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();

IIC_SendByte(0x40);//选择输出DAC的控制数据
IIC_WaitAck();

IIC_SendByte(temp);
IIC_WaitAck();

IIC_Stop();
}

iic.h

#ifndef __IIC_H
#define __IIC_H

void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
void writeDAC(unsigned char temp);
#endif

onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

unsigned char rd_temperature(void); //; ;
float read18b20();//添加头文件
#endif

onewire.c

/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include "stc15.h"
#include "onewire.h"

sbit DQ = P1^4; //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t=t*12; //这一行一定要添加。。
while(t--);
}

//通过单总线向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;
}

//读取温度函数
float read18b20()
{
unsigned char high,low;
unsigned int temp;
float xx;

init_ds18b20();
Write_DS18B20(0xCC); //跳过ROM
Write_DS18B20(0x44); //开始转换
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0xCC); //跳过ROM
Write_DS18B20(0xBE);//读取
Delay_OneWire(200);

low = Read_DS18B20(); //先低
high =Read_DS18B20(); //后高

temp= (high&0x1F) <<8 |low;
xx=temp*0.0625;
return xx;
}