题目:
用到的模块:
-
LED单个点亮(建议用sbit,文件开头定义单个引脚)
-
数码管动态显示
-
矩阵键盘
-
ds18b20,用到onewire.c
-
DAC转化(步骤见文章末尾的易错点),用到iic.c
main.c代码
#include "intrins.h"
#include "reg52.h"
#include "onewire.h"
#include "iic.h"
sfr P4=0xc0;
sbit r1=P3^2;
sbit r2=P3^3;
sbit l1=P4^4;
sbit l2=P4^2;
sbit L1=P0^0;
sbit L2=P0^1;
sbit L3=P0^2;
sbit L4=P0^3;
unsigned char 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,};
unsigned char code t_display_dot[]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
unsigned char mode=1;
unsigned int temp;
unsigned int temp_set=25;
unsigned int dac0;
unsigned int temp_SMG;
unsigned int dac_SMG;
unsigned char mode_1=1;
//
void SelectHC138(unsigned char channel,unsigned char dat);
void InitSys();
void SMG_bit(unsigned char pos,unsigned char num);
void SMG();
void Delay2ms(); //@11.0592MHz
void DS18B20();
void Delay(unsigned char t);
void ScanKeys();
void Delay_key(unsigned char t);
void LED();
void DAC();
///
void main()
{
InitSys();
while(1)
{
LED();
ScanKeys();
DS18B20();
SMG();
DAC();
}
}
//
void SelectHC138(unsigned char channel,unsigned char dat)
{
P0=dat;
switch(channel)
{
case 0:
P2=P2&0x1f|0x00;
break;
case 4:
P2=P2&0x1f|0x80;
break;
case 5:
P2=P2&0x1f|0xa0;
break;
case 6:
P2=P2&0x1f|0xc0;
break;
case 7:
P2=P2&0x1f|0xe0;
break;
}
P2=P2&0x1f|0x00;
}
void InitSys()
{
SelectHC138(4,0xff);
SelectHC138(5,0x00);
SelectHC138(6,0xff);
SelectHC138(7,0xff);
}
void SMG_bit(unsigned char pos,unsigned char num)
{
SelectHC138(6,0x01<<pos);
SelectHC138(7,num);
Delay2ms();
SelectHC138(7,0xff);
}
void SMG()
{
switch(mode)
{
case 1:
SMG_bit(0,~0x39);
SMG_bit(7,~t_display[temp_SMG%10]);
SMG_bit(6,~t_display[temp_SMG/10%10]);
SMG_bit(5,~t_display_dot[temp_SMG/100%10]);
SMG_bit(4,~t_display[temp_SMG/1000]);
break;
case 2:
SMG_bit(0,~0x73);
SMG_bit(7,~t_display[temp_set%10]);
SMG_bit(6,~t_display[temp_set/10]);
break;
case 3:
SMG_bit(0,~0x77);
SMG_bit(7,~t_display[dac_SMG%10]);
SMG_bit(6,~t_display[dac_SMG%100/10]);
SMG_bit(5,~t_display_dot[dac_SMG/100]);
break;
}
}
void Delay2ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 22;
j = 128;
do
{
while (--j);
} while (--i);
}
void DS18B20()
{
unsigned char MSB,LSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay(500);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB=Read_DS18B20();
MSB=Read_DS18B20();
temp=MSB;
temp=(temp<<8)|LSB;
temp=temp>>4;
temp_SMG=temp*100+(LSB&0x0f)*6.25;
temp=temp+(LSB&0x0f)*0.0625;
}
void ScanKeys()
{
//S4
r1=1;
l1=l2=1;
r2=0;
if(l1==0)
{
Delay_key(20);
if(l1==0)
{
while(l1==0)
{
SMG();
}
if(mode==3)
mode=1;
else
mode++;
}
}
//S8
r1=1;
l1=l2=1;
r2=0;
if(l2==0)
{
Delay_key(20);
if(l2==0)
{
while(l2==0)
{
SMG();
}
//
if(mode==2)
temp_set--;
}
}
//S5
r2=1;
l1=l2=1;
r1=0;
if(l1==0)
{
Delay_key(20);
if(l1==0)
{
while(l1==0)
{
SMG();
}
//
if(mode_1==1)
mode_1=2;
else
mode_1=1;
}
}
//S9
r2=1;
l1=l2=1;
r1=0;
if(l2==0)
{
Delay_key(20);
if(l2==0)
{
while(l2==0)
{
SMG();
}
//
if(mode==2)
temp_set++;
}
}
}
void LED()
{
InitSys();
if(mode_1==1)
{
P2=P2&0x1f|0x80;
L1=0;
P2=P2&0x1f|0x00;
}
if(mode_1==2)
{
P2=P2&0x1f|0x80;
L1=1;
P2=P2&0x1f|0x00;
}
if(mode==1)
{
P2=P2&0x1f|0x80;
L2=0;
P2=P2&0x1f|0x00;
}
if(mode==2)
{
P2=P2&0x1f|0x80;
L3=0;
P2=P2&0x1f|0x00;
}
if(mode==3)
{
P2=P2&0x1f|0x80;
L4=0;
P2=P2&0x1f|0x00;
}
}
void DAC()
{
if(mode_1==1)
{
if(temp<temp_set)
{
dac_SMG=0;
dac0=0;
output(dac0);
}
else
{
dac_SMG=500;
dac0=255;
output(dac0);
}
}
else
{
if(temp<=20)
{
dac_SMG=100;
dac0=1/5*255;
output(dac0);
}
else if(temp>=40)
{
dac_SMG=400;
dac0=4/5*255;
output(dac0);
}
else
{
//y=kx+b;4=40k+b;1=20k+b;20k=3,b=-2
dac0=((3/20)*temp-2)/5*255;
dac_SMG=((3.0/20.0)*temp-2)*100;
output(dac0);
}
}
}
void Delay(unsigned char t)
{
while(t--)
{
SMG();
ScanKeys();
LED();
DAC();
}
}
void Delay_key(unsigned char t)
{
while(t--)
{
SMG();
LED();
DAC();
}
}
iic.c代码,注意最后一个函数是自己写的,且要将这个函数声明加入iic.h中
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include "reg52.h"
#include "intrins.h"
#define DELAY_TIME 50
#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 output(unsigned char dac0)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(dac0);
IIC_WaitAck();
IIC_Stop();
}
iic.h(最后加入自己在iic.c中写的函数的声明)
#ifndef __IIC_H__
#define __IIC_H__
#include "reg52.h"
#include "intrins.h"
#define DELAY_TIME 50
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_SendAck(bit ackbit);
bit IIC_WaitAck(void);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
void output(unsigned char dac0);
#endif
要点及易错点:
-
DAC写入是要将数据*255/5.0的
-
计算斜率的时候,要加小数点,不然计算会错误,例如:3/20是错的,要写成(3.0/20.0)
-
矩阵键盘用到P4端口的时候,要在文件的开头加上sfr P4=0xc0,
-
DAC写入不要忘记步骤:
-
启动start
-
写入0x90
-
等回应
-
写入0x40
-
等回应
-
写入dac数据(要将电压转换成虚拟值,所以要/5*255)
-
等回应
-
结束
5. DS18B20模块的Delay函数中,while(t--)的循环下要有所有的显示+读取+按键扫描
6.按键扫描的延时函数中,while(t--)的循环下要有所有的显示+读取,但不要加入按键扫描
作者的话:
本系列不是教学篇,为速通版。因此涉及打破砂锅问到底的逻辑部分较少。
C语言教程可移步曾经发过的C语言速通教程。
有建议欢迎指出,也欢迎友好交流!
另也欢迎关注其他平台上本人的账号 如下:
知乎:youzuos
微信公众号:知识薪火站
感谢支持!