若有错误,欢迎评论指正!
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);
unsigned char Read_PCF8591(unsigned char mode);
#endif
iic.c
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#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;
}
//电压采集函数
unsigned char Read_PCF8591(unsigned char mode)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
if(mode == 1)
IIC_SendByte(0x01); //光敏电阻通道
else if(mode == 3)
IIC_SendByte(0x03); //电位器2通道
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
smg.h
#ifndef __SMG_H
#define __SMG_H
unsigned char code SMG_duanma[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
void Delay_SMG(unsigned char t);
void Select(unsigned char channel);
void DisplaySMG_Bit(unsigned char pos,unsigned char dat);
void Display_all(unsigned char dat);
#endif
smg.c
#include "reg52.h"
void Delay_SMG(unsigned char t)
{
while(t--);
}
void Select(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;
}
}
void DisplaySMG_Bit(unsigned char pos,unsigned char dat)
{
P0 = 0xff;
Select(6);
P0 = 0x01 << pos;
Select(7);
P0 = dat;
}
void Display_all(unsigned char dat)
{
Select(6);
P0 = 0xff;
Select(7);
P0 = dat;
}
main.c
#include "STC15F2K60S2.H"
#include "smg.h"
#include "iic.h"
unsigned int count_fre; //用于保存脉冲数量
unsigned char count_500ms; //用于保存0.5s计数
unsigned int dat_fre; //用于保存频率数据
unsigned char dat_per; //用于保存周期数据
unsigned char mode = 1; //用于判断读取的模式
unsigned int dat_Dac; //用于保存电压数据
unsigned char flag_S4; //用于当前显示的界面
unsigned int para_dac; //用于保存电压参数
unsigned int para_fre; //用于保存频率数据
unsigned char count_S7; //用于判断S7是否是长按
unsigned char flag_S7; //用于判断是否长按
unsigned char flag_led; //用于判断led功能是否启用
sbit S4 = P3^3;
sbit S5 = P3^2;
sbit S6 = P3^1;
sbit S7 = P3^0;
//系统初始化函数
void Init_Sys()
{
Select(4);
P0 = 0xff;
Select(5);
P0 = 0x00;
Select(0);
}
//ne555频率读取相关函数
void Timer0Init(void) //@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x04; //设置定时器模式为计数模式
TL0 = 0xff; //设置定时初值
TH0 = 0xff; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer1Init(void) //10毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xF0; //设置定时初值
TH1 = 0xD8; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
void Uart_Timer0() interrupt 1
{
count_fre++;
}
void Uart_Timer1() interrupt 3
{
count_500ms++;
if(count_500ms == 50)
{
count_500ms = 0;
dat_fre = count_fre;
dat_per = 1000000/dat_fre;
count_fre = 0;
}
}
//周期以及频率显示函数
void Display_fre()
{
DisplaySMG_Bit(0,0x8e); Delay_SMG(100);
if(dat_fre > 999999)
{
DisplaySMG_Bit(1,SMG_duanma[dat_fre / 1000000]); Delay_SMG(100);
}
if(dat_fre > 99999)
{
DisplaySMG_Bit(2,SMG_duanma[dat_fre / 100000 % 10]); Delay_SMG(100);
}
if(dat_fre > 9999)
{
DisplaySMG_Bit(3,SMG_duanma[dat_fre / 10000 % 10]); Delay_SMG(100);
}
if(dat_fre > 999)
{
DisplaySMG_Bit(4,SMG_duanma[dat_fre / 1000 % 10]); Delay_SMG(100);
}
if(dat_fre > 99)
{
DisplaySMG_Bit(5,SMG_duanma[dat_fre / 100 % 10]); Delay_SMG(100);
}
if(dat_fre > 9)
{
DisplaySMG_Bit(6,SMG_duanma[dat_fre / 10 % 10]); Delay_SMG(100);
}
DisplaySMG_Bit(7,SMG_duanma[dat_fre % 10]); Delay_SMG(100);
Display_all(0xff);
}
void Display_per()
{
DisplaySMG_Bit(0,0xc8); Delay_SMG(100);
if(dat_per > 999999)
{
DisplaySMG_Bit(1,SMG_duanma[dat_per / 1000000]); Delay_SMG(100);
}
if(dat_per > 99999)
{
DisplaySMG_Bit(2,SMG_duanma[dat_per / 100000 % 10]); Delay_SMG(100);
}
if(dat_per > 9999)
{
DisplaySMG_Bit(3,SMG_duanma[dat_per / 10000 % 10]); Delay_SMG(100);
}
if(dat_per > 999)
{
DisplaySMG_Bit(4,SMG_duanma[dat_per / 1000 % 10]); Delay_SMG(100);
}
if(dat_per > 99)
{
DisplaySMG_Bit(5,SMG_duanma[dat_per / 100 % 10]); Delay_SMG(100);
}
if(dat_per > 9)
{
DisplaySMG_Bit(6,SMG_duanma[dat_per / 10 % 10]); Delay_SMG(100);
}
DisplaySMG_Bit(7,SMG_duanma[dat_per % 10]); Delay_SMG(100);
Display_all(0xff);
}
//电压读取及显示函数
void Read_Dac()
{
dat_Dac = Read_PCF8591(mode) * 50.0 / 255 * 10; //电压读取并进行转换
}
void Display_Dac()
{
DisplaySMG_Bit(0,0xc1); Delay_SMG(100);
DisplaySMG_Bit(1,0xbf); Delay_SMG(100);
DisplaySMG_Bit(2,SMG_duanma[mode]); Delay_SMG(100);
DisplaySMG_Bit(3,0xff); Delay_SMG(100);
DisplaySMG_Bit(4,0xff); Delay_SMG(100);
DisplaySMG_Bit(5,SMG_duanma[dat_Dac / 100] & 0x7f); Delay_SMG(100);
DisplaySMG_Bit(6,SMG_duanma[dat_Dac / 10 % 10]); Delay_SMG(100);
DisplaySMG_Bit(7,SMG_duanma[dat_Dac % 10]); Delay_SMG(100);
Display_all(0xff);
}
//显示总函数
void Display()
{
switch(flag_S4)
{
case 0: Display_fre(); break;
case 1: Display_per(); break;
case 2: Display_Dac(); break;
}
}
//按键相关函数
void Delay_Key(unsigned char t)
{
while(t--);
}
void Scan_Key()
{
//S4按键界面切换
if(S4 == 0)
{
Delay_Key(100);
if(S4 == 0)
{
while(S4 == 0)
Display();
flag_S4++;
if(flag_S4 == 3)
flag_S4 = 0;
if(flag_S4 == 2)
mode = 1;
}
}
//S5模式切换
if(S5 == 0)
{
Delay_Key(100);
if(S5 == 0)
{
while(S5 == 0)
Display();
if(mode == 1)
mode = 3;
else if(mode == 3)
mode = 1;
}
}
//S6电压缓存
if(S6 == 0)
{
Delay_Key(100);
if(S6 == 0)
{
while(S6 == 0)
Display();
para_dac = Read_PCF8591(3) * 50.0 / 255 * 10;
}
}
//S7频率缓存
if(S7 == 0)
{
Delay_Key(100);
if(S7 == 0)
{
flag_S7 = 1; //S7按下
while(S7 == 0)
Display();
flag_S7 = 0; //松开S7
if(count_S7 <= 100) //计时不到1s,判断为短按
{
count_S7 = 0;
para_fre = dat_fre;
}
else //计时超过1s,判断为长按
{
count_S7 = 0;
flag_led = ~flag_led;
}
}
}
}
//长按判断函数
void Timer2Init(void) //10毫秒@12.000MHz
{
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0xF0; //设置定时初值
T2H = 0xD8; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04;
EA = 1;
}
void Uart_Timer2() interrupt 12
{
if(flag_S7 == 1)
{
count_S7++;
}
}
//led相关函数
void led()
{
if(flag_led == 0) //led功能开启
{
if((Read_PCF8591(3) * 50.0 / 255 * 10) > para_dac) //L1
{
Select(4);
P0 = P0 & 0xfe;
Select(0);
}
if(dat_fre > para_fre) //L2
{
Select(4);
P0 = P0 & 0xfd;
Select(0);
}
switch(flag_S4)
{
case 0: //L3
Select(4);
P0 = P0 & 0xfb;
Select(0);
break;
case 1: //L4
Select(4);
P0 = P0 & 0xf7;
Select(0);
break;
case 2: //L5
Select(4);
P0 = P0 & 0xef;
Select(0);
break;
}
}
else //led功能关闭
{
Select(4);
P0 = 0xff;
Select(0);
}
}
void main()
{
Init_Sys();
Timer0Init();
Timer1Init();
Timer2Init();
while(1)
{
Read_Dac();
Display();
Scan_Key();
led();
}
}