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_From_AT24C02();
void Write_to_AT24C02(unsigned char dat);
unsigned char Read_AIN3_From_PCF8951();
#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;
EA=0;
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);
}
EA=1;
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
EA=0;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
EA=1;
return da;
}
unsigned char Read_AIN3_From_PCF8951()
{
unsigned char dat;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
dat=IIC_RecByte();
IIC_SendAck(0);
IIC_Stop();
return dat;
}
void Write_to_AT24C02(unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(0x00);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char Read_From_AT24C02()
{
unsigned char dat;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(0x00);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
dat=IIC_RecByte();
IIC_SendAck(0);
IIC_Stop();
return dat;
}
key.h
#include <stc15f2k60s2.h>
#include <iic.h>
sbit KEY_OUT_0=P4^4;
sbit KEY_OUT_1=P4^2;
sbit KEY_OUT_2=P3^5;
sbit KEY_OUT_3=P3^4;
sbit KEY_IN_0=P3^0;
sbit KEY_IN_1=P3^1;
sbit KEY_IN_2=P3^2;
sbit KEY_IN_3=P3^3;
unsigned char keySta[4][4]={
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
};
unsigned char keybuff[4][4]={
{0xff,0xff,0xff,0xff},
{0xff,0xff,0xff,0xff},
{0xff,0xff,0xff,0xff},
{0xff,0xff,0xff,0xff},
};
unsigned char backup[4][4]={
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
};
unsigned char code keymap[4][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16},
};
unsigned char dat=0;
//=======================全局变量
unsigned char mode=0;
char Vol_p=25;
unsigned char Now_count=0;
unsigned char NO_Reflect=0;
//==============================
unsigned char Scope=0;
void keyscan()
{
unsigned char i,j;
keybuff[0][Scope]=(keybuff[0][Scope]<<1)|KEY_IN_0;
keybuff[1][Scope]=(keybuff[1][Scope]<<1)|KEY_IN_1;
keybuff[2][Scope]=(keybuff[2][Scope]<<1)|KEY_IN_2;
keybuff[3][Scope]=(keybuff[3][Scope]<<1)|KEY_IN_3;
Scope++;
Scope&=0x03;
switch(Scope)
{
case 0: KEY_OUT_3=1;KEY_OUT_0=0; break;
case 1: KEY_OUT_0=1;KEY_OUT_1=0; break;
case 2: KEY_OUT_1=1;KEY_OUT_2=0; break;
case 3: KEY_OUT_2=1;KEY_OUT_3=0; break;
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if((keybuff[i][j]&0x0f)==0x00) keySta[i][j]=0;
else if((keybuff[i][j]&0x0f)==0x0f) keySta[i][j]=1;
}
}
}
void keyAction(unsigned char keycode)
{
if(keycode==12)//S17
{
if(mode==1)
{
NO_Reflect=0;
Vol_p=Vol_p-5;
if(Vol_p<0) Vol_p=50;
}
if(mode==0) NO_Reflect++;
if(mode==2) NO_Reflect++;
}
if(keycode==16)//S16
{
if(mode==1)
{
NO_Reflect=0;
Vol_p=Vol_p+5;
if(Vol_p>50) Vol_p=0;
}
if(mode==0) NO_Reflect++;
if(mode==2) NO_Reflect++;
}
if(keycode==11)//S13
{
if(mode==2) {Now_count=0;NO_Reflect=0;}
if(mode==0) NO_Reflect++;
if(mode==1) NO_Reflect++;
}
if(keycode==15) //S12
{
mode++;
NO_Reflect=0;
if(mode!=1) Write_to_AT24C02(Vol_p);
if(mode>2) mode=0;
}
}
void key_drive()
{
unsigned char i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(backup[i][j]!=keySta[i][j])
{
if(keySta[i][j]==0)
{
keyAction(keymap[i][j]);
}
}
backup[i][j]=keySta[i][j];
}
}
}
display.h
#ifndef _display_h
#define _display_h
void ledscan();
void led_play();
extern unsigned int Vol_in;
#endif
display.c
#include <stc15f2k60s2.h>
#include <key.h>
#include <iic.h>
unsigned char code smgduan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char index=0;
unsigned char disbuff[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
unsigned int Vol_in=0;
void ledscan()
{
P2=(P2&0x1f)|0xe0;
P0=0xff;
P2&=0x1f;
P2=(P2&0x1f)|0xc0;
P0=0x80>>index;
P2&=0x1f;
P2=(P2&0x1f)|0xe0;
P0=disbuff[index];
P2&=0x1f;
if(++index>8) index=0;
}
void led_play()
{
Vol_in=Read_AIN3_From_PCF8951()*1.960784;
if(mode==0)
{
disbuff[7]=0xc1;
disbuff[6]=0xff;
disbuff[5]=0xff;
disbuff[4]=0xff;
disbuff[3]=0xff;
disbuff[2]=smgduan[Vol_in/100]&0x7f;
disbuff[1]=smgduan[Vol_in%100/10];
disbuff[0]=smgduan[Vol_in%10];
}
else if(mode==1)
{
disbuff[7]=0x8c;
disbuff[6]=0xff;
disbuff[5]=0xff;
disbuff[4]=0xff;
disbuff[3]=0xff;
disbuff[2]=smgduan[Vol_p/10]&0x7f;
disbuff[1]=smgduan[Vol_p%10];
disbuff[0]=smgduan[0];
}
else if(mode==2)
{
disbuff[7]=0xc8;
disbuff[6]=0xff;
disbuff[5]=0xff;
disbuff[4]=0xff;
disbuff[3]=0xff;
disbuff[2]=0xff;
disbuff[1]=0xff;
if(Now_count>=0 && Now_count<9)
{
disbuff[0]=smgduan[Now_count];
}else if(Now_count>=9 && Now_count<99)
{
disbuff[1]=smgduan[Now_count/10];
disbuff[0]=smgduan[Now_count%10];
}
}
}
main.c
#include <stc15f2k60s2.h>
#include <display.h>
#include <key.h>
#include <iic.h>
//===========================变量定义
sbit LED1=P0^0;
sbit LED2=P0^1;
sbit LED3=P0^2;
unsigned int LED1_count=0;
bit Before_big=0,Now_equall=0;
unsigned char i=0;
//==================================
//===========================函数声明
void InitSystem();
void Timer0Init(void);
void led_show();
void Count_add();
//==================================
void main()
{
Vol_p=Read_From_AT24C02();
InitSystem();
Write_to_AT24C02(25);
Timer0Init();
EA=1;
while(1)
{
key_drive();
led_play();
led_show();
Count_add();
}
}
void InitSystem()
{
P2=(P2&0x1f)|0x80;
P0=0xff;
P2&=0x1f;
P2=(P2&0x1f)|0xa0;
P0=0x00;
P2&=0x1f;
P2=(P2&0x1f)|0xc0;
P0=0xff;
P2&=0x1f;
P2=(P2&0x1f)|0xe0;
P0=0xff;
P2&=0x1f;
}
void Timer0Init(void) //2毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x9A; //设置定时初值
TH0 = 0xA9; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
}
void Timer0() interrupt 1
{
if(Vol_in<Vol_p*10) LED1_count++;
TL0 = 0x9A; //设置定时初值
TH0 = 0xA9; //设置定时初值
keyscan();
ledscan();
}
void led_show()
{
P2=(P2&0x1f)|0x80;
P0=0xff;
if(Vol_in<Vol_p*10)
{
if(LED1_count>2500) LED1=0;
else LED1=1;
}
if(Vol_in>=Vol_p*10) {LED1=1;LED1_count=0;}
if(Now_count%2==1) LED2=0;
else LED2=1;
if(NO_Reflect>=3) LED3=0;
else if(NO_Reflect<3) LED3=1;
P2&=0x1f;
}
void Count_add()
{
if(Vol_in>Vol_p*10) //Vol_in 是AD转换值 范围0-500
{
Before_big=1; // Before_big是前一刻 输入电压比参考电压大的 表示位
}
if(Before_big==1)
{
if(Vol_in==Vol_p*10) //Vol_p是参考电压 范围0-50
{
Now_equall=1; //Now_equall是 输入电压比参考电压 相等的标志位
}
}
if((Before_big==1) && (Now_equall==1))
{
Now_count++; //Now_count是计数值
Before_big=0;
Now_equall=0;
}
}
避坑指南:
①计数界面计数值不正常显示,可以试试在IIC通信中,读数据和写数据时关闭EA,结束后打开EA;
②做完NE555模块时一定要把短接帽拿下来!!!不然矩阵键盘最右侧一列就没用了!!!!估计这个憨批问题就出在我这个憨批身上了!!
③用到的S12 S13 S17 S16按键我是用矩阵键盘识别(状态机法)的,个人感觉只要背过了,比赛稳拿把掐 就是码的有点多;
④分文件编程时巧用全局变量,太方便了!!!如果main.c的变量想在其他.c文件里用,可以在非main.c文件里定义全局变量,main.c文件再引用全局变量。
.
.
保省二冲国二!!!!!!!!!!冲冲冲