-
138译码器 ,led控制
led低电平点亮0xff全部关闭,0x00打开全部
void InitHC138(unsigned char channel)
{
switch(channel)
{
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;
case 0:P2 = (P2 & 0x1f) | 0x00;break;
}
P2 = (P2 & 0x1f) | 0x00;
}
//系统初始化,先给数值,后选位
void Init_System()
{
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
SMG_All(0xff);
}
-
数码管动态显示
原理图y6c选位置,y7设置值
p0=0x00;po<<=1; 0000变为0010
p0=0x00;po<<=1; p0|=1;变为0011
void DisPlaysmg_Bit(unsigned char value,unsigned char pos)
{
P0=0x01<<pos;
InitHC138(6);选择位置
P0=value;或者P0=~value;共阳变共阴
InitHC138(7); 选择值
}
void dongtai()
{显示值,每个值延时500
DisPlaysmg_Bit(SMG_duanma[2],0);
Delay(500);
DisPlaysmg_Bit(SMG_duanma[0],1);
Delay(500);
}
延迟中若要显示则必须用到该函数:
void Delayzhuyong(unsigned int t)
{
while(t--)
{
dongtai();
}
}
-
蜂鸣器继电器
蜂鸣器和继电器由Y5控制12。控制时,先选择Y5,然后编写P0即可控制,0为关,1为开
蜂鸣器和继电器由Y5控制12。控制时,先选择Y5,然后编写P0即可控制,0为关,1为开
void OutPutP0(unsigned char channel, unsigned char dat)
{
InitHC138(channel);
P0 = dat;
}
OutPutP0(5,0x10);开启
OutPutP0(5,0x00);关闭
-
独立按键
if(S7 == 0)
{
Delay(100);按键防抖,如按键时候需要显示则数码管显示操作
}
矩阵键盘
选某行=0,列为1,其他行为1;
当检测到某列为0,判断为值,例如1行1列等于0,则为1,例如:
sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;
sbit C4 = P3^4;
sbit C3 = P3^5;
sbit C2 = P4^2;
sbit C1 = P4^4;
键盘扫描函数:
R1 = 0;
R2 = R3 = R4 = 1;
C1 = C2 = C3 = C4 =1;
if(C1 == 0)
{
while(C1 == 0)//注意显示问题;
key_num = 0;
DisplayKeyNum(SMG_duanma[key_num]);
}
外部中断
手册查6.5,6.6,7.1,7.2相关寄存器:触发引脚:into为p32,int1为p33
void Init_INT0()
{
IT0 = 1;
EX0 = 1; //若为0;低电平触发,即按下持续期间触发
EA = 1;
}
void ServiceINT0() interrupt 0
{
stat_int = 1;
}
当stat_int = 1;时候执行操作
-
定时器中断
开启stc-isp,系统频率12,定时器0,16位自动重载,12t
开启stc-isp,系统频率12,定时器0,16位自动重载,12t,8位为0-225,16位为65535,自动重载意味着不用再中断函数输入th0,tl0。
然后后面加入:ET0 = 1; EA=1;
void Timer_Init(void)
{
AUXR |= 0x80;
TMOD &= 0xF0;
TL0 = 0xCD;
TH0 = 0xD4;
TF0 = 0;
TR0 = 1;
ET0 = 1;手动添加
EA=1;
}
//中断服务函数
void timer0() interrupt 1
{
//1ms进一次中断。
}
利用PWM控制灯光亮度:定时器定时10ms,代表频率,50%亮度意味着前5ms灯亮,后5ms灯灭。
void ServiceTimer0() interrupt 1
{
// TH0 = (65535 - 100) / 256;
// TL0 = (65535 - 100) % 256;
// 若未开重载
count++;
if(count == pwm_duty)
{
L1 = 1;灯关
}
else if(count == 100)
{
L1 = 0;开
count = 0;
}
温度传感器
不记得记得看赛点手册,初始化,忽略rom,启动温度转换,等待转换完成
void Read_Dsiplay_DS18B20()
{
unsigned char LSB,MSB;
unsigned int temp = 0;
init_ds18b20(); //初始化DS18B20
Write_DS18B20(0xcc); //忽略ROM操作
Write_DS18B20(0x44); //启动温度转换
DisplaySMG_Temp();
init_ds18b20(); //初始化DS18B20
Write_DS18B20(0xcc); //忽略ROM操作
Write_DS18B20(0xbe); //读出内部存储器
LSB = Read_DS18B20(); //第0字节:温度低8位
MSB = Read_DS18B20(); //第1字节:温度高8位
init_ds18b20(); //初始化,停止读取
temp = MSB; //合成16位温度原始数据
temp = (temp << 8) | LSB;
temp_ds18b20 = temp * 0.0625; //计算实际温度值
smg_ds18b20 = temp_ds18b20 * 10;
DisplaySMG_Temp();
}
DS18B20的单总线底层驱动代码:若提供的是52的,需要将时序*10,但要注意到底需要不需要进行修改
-
实时时钟
时钟写
void write_Ds1302()
{
unsigned char i=0;
unsigned char adr=0x80;
Write_Ds1302(0x8e,0x00);允许时钟写开
for(i=0;i<7;i++)
{
Write_Ds1302(adr,read_time[i]);
adr+=2;
}
Write_Ds1302(0x8e,0x80);关
}
时钟读
void read_tem()
{
unsigned char i=0;
unsigned char t,date1;
unsigned char adr=0x81;
for(i=0;i<7;i++)
{
t=Read_Ds1302(adr);
date1=t/16;
date1=date1*10;
read_time[i]=date1+t%16;
adr+=2;
}
}
-
iic
-
PCF8591(光敏电阻,可调电阻,ad(0x0),da转换)
PCF8591读操作地址为:0x91;而写操作地址则为:0x90
ad模拟转数字转换流程:
1-发送写设备地址,选择IIC总线上的PCF8591器件。
2--发送控制字节,选择模拟量输入模式和通道。
3--发送读设备地址,选择IIC总线上的PCF8591器件。
4--读取PCF8591中目标通道的数据。
ad转换,实际上是读取电阻中的值
void Read_AIN3()
{
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0x90); //PCF8591的写设备地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(0x03); //写入PCF8591的控制字节
// IIC_SendByte(0x01); //通道1,光敏电阻电压
IIC_WaitAck(); //等待从机应答
IIC_Stop(); //IIC总线停止信号
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0x91); //PCF8591的读设备地址
IIC_WaitAck(); //等待从机应答
dat = IIC_RecByte(); //读取PCF8591通道3的数据
IIC_Ack(0); //产生非应答信号
IIC_Stop(); //IIC总线停止信号
}
光明电阻在ani1引脚,可调电阻在ani3引脚
设置dac可调电阻输出为:则第六位为1,第0,1位为11
{
IIC_Start();
IIC_SendByte(0x90); //PCF8591的写设备地址
IIC_WaitAck();
IIC_SendByte(0x43); //输出DAC,转换AIN3
IIC_WaitAck();
IIC_SendByte(dat); //设置DAC电压输出参数
IIC_WaitAck(); //产生非应答信号
IIC_Stop();
}
-
存储器24c02
24C02的设备的读操作地址为:0xA1;而写操作地址则为:0xA0。
4C02的字节写操作,参考代码:
void Write_24C02(unsigned char addr, unsigned char dat)
{
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0xa0); //24C02的写设备地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(addr); //内存字节字节
IIC_WaitAck(); //等待从机应答
IIC_SendByte(dat); //写入目标数据
IIC_WaitAck(); //等待从机应答
IIC_Stop(); //IIC总线停止信号
}
24C02的字节读操作,参考代码:
unsigned char Read_24C02(unsigned char addr)
{
unsigned char tmp;
//进行一个伪写操作
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0xa0); //24C02写设备地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(addr); //内存自己地址
IIC_WaitAck(); //等待从机应答
//进行字节读操作
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0xa1); //24C02读设备地址
IIC_WaitAck(); //等待从机应答
tmp = IIC_RecByte(); //读取目标数据
IIC_Ack(0); //产生非应答信号
IIC_Stop(); //IIC总线停止信号
return tmp;
}
55频率技术
实际上将t0当作计数器,t1当作定时器。计算每秒内脉冲的数量
例如
void Init_Timer()
{
//定时器0用作计数,8位重装
TH0 = 0XFF;
TL0 = 0XFF;
//定时器1用作定时,定时时间50ms
TH1 = (65535 - 50000 + 1) / 256;
TL1 = (65535 - 50000 + 1) % 256;
TMOD = 0X16;//0001 0110
ET0 = 1;
ET1 = 1;
EA = 1;
TR0 = 1;
TR1 = 1;
}
void Service_T0() interrupt 1
{
count_f++;
}
void Service_T1() interrupt 3
{
TH1 = (65535 - 50000 + 1) / 256;
TL1 = (65535 - 50000 + 1) % 256;
count_t++;
if(count_t == 20)
{
dat_f = count_f;
count_f = 0;
count_t = 0;
}
}
上述代码统计每秒内脉定时器中断数量