每次建好工程文件夹,里边包含User(放工程文件,mian.c,可以在这里写如同我这个文章的文本文档)、Driver(存放底层文件如Led.c,Led.h等)
新建的工程先搭建框架,可以先书写底层函数(此次书写了五个函数并包含相应的头文件共十个底层文件)
比如先用3个IO口控制74HC138译码器,控制Y4为低电平;当Y4为低电平时,或非门74HC02控制Y4C为高电平,使74HC573的OE端口有效,OE端口有效时,可使用P0口控制LED的亮灭。
可以去多了解74HC138译码器,74HC02或非门,74HC573八路输出透明锁存器的相关内容会更好理解
#include
//关闭外设
void System_Init()
{
P0 = 0xff;
P2 = P2 & 0x1f | 0x80;
P2 &= 0x1f;
P0 = 0x00;
P2 = P2 & 0x1f | 0xa0;
P2 &= 0x1f;
}
//头文件
#include
void System_Init();
与初始化底层驱动专用文件同理,需要了解对应的锁存器控制,可以在使用的芯片数据手册查看
#include
void Led_Disp(unsigned char addr,enable)//LED
{
static unsigned char temp = 0x00;
static unsigned char temp_Old = 0xff;
if(enable)
temp |=0x01 << addr;
else
temp&= ~ (0x01 << addr);
if(temp != temp_Old)
{
P0 = ~ temp;
P2 = P2 & 0x1f | 0x80;
P2 &= 0x1f;
temp_Old = temp;
}
}
void Beep(unsigned char flag)//蜂鸣器
{
static unsigned char temp = 0x00;
static unsigned char temp_Old = 0xff;
if(flag)
temp |=0x40 ;
else
temp &= ~ 0x40 ;
if(temp != temp_Old)
{
P0 = ~ temp;
P2 = P2 & 0x1f | 0xa0;
P2 &= 0x1f;
temp_Old = temp;
}
}
void Relay(unsigned char flag)//继电器
{
static unsigned char temp = 0x00;
static unsigned char temp_Old = 0xff;
if(flag)
temp |= 0x10 ;
else
temp &= ~ 0x10 ;
if(temp != temp_Old)
{
P0 = ~ temp;
P2 = P2 & 0x1f | 0xa0;
P2 &= 0x1f;
temp_Old = temp;
}
}
//头文件
#include
void Led_Disp(unsigned char addr,enable);
(板子上的按键从按键4开始到按键19,可根据实际硬件修改)
#include
unsigned char Key_Read()
{
unsigned char temp = 0;
P44 = 0;P42 = 1; P35 = 1;P34 = 1;//这个仿真没有P4口,不适用,但是实际运行使用这个
P37 = 0; P36 = 1; P35 = 1; P34 = 1;
if(P33 == 0) temp = 4;
if(P32 == 0) temp = 5;
if(P31 == 0) temp = 6;
if(P30 == 0) temp = 7;
P37 = 1; P36 = 0; P35 = 1; P34 = 1;
if(P33 == 0) temp = 8;
if(P32 == 0) temp = 9;
if(P31 == 0) temp = 10;
if(P30 == 0) temp = 11;
P37 = 1; P36 = 1; P35 = 0; P34 = 1;
if(P33 == 0) temp = 12;
if(P32 == 0) temp = 13;
if(P31 == 0) temp = 14;
if(P30 == 0) temp = 15;
P37 = 1; P36 = 1; P35 = 1; P34 = 0;
if(P33 == 0) temp = 16;
if(P32 == 0) temp = 17;
if(P31 == 0) temp = 18;
if(P30 == 0) temp = 19;
return temp;
}
//头文件
#include
unsigned char Key_Read();
#include
unsigned char Seg_Dula[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};//数码管段码储存数组
unsigned char Seg_Wela[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//数码管位码储存数组
void Seg_Disp(unsigned char wela,dula,point)
{
P0 = 0xff; //
P2 = P2 & 0x1f |0xe0;
P2 &= 0x1f;
P0 = Seg_Wela[wela];
P2 = P2 & 0x1f |0xc0;
P2 &= 0x1f;
P0 = Seg_Dula[dula];
if(point)
P0 &= 0x7f;
P2 = P2 & 0x1f |0xe0;
P2 &= 0x1f;
}
//头文件
#include
void Seg_Disp(unsigned char wela,dula,point);
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include "iic.h"
#include "intrins.h"
#define DELAY_TIME 5
#define Photo_Res_Channel 0x41
#define Adj_Res_Channel 0x43
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;
}
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;
}
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;
}
//入口参数:要进行转换的通道控制位
//返回值:ADC转换的数值
//函数功能:对指定的通道进行ADC转换,函数返回转换的数值
unsigned char Pcf8591_Adc(unsigned char channel_num_contrl)
{
unsigned char temp;
IIC_Start();//发送开启信号
IIC_SendByte(0x90);//选择PCF8591芯片,确定写的模式
IIC_WaitAck();//等待PCF8591反馈
IIC_SendByte(channel_num_contrl);//确定要转换的通道(顺便,使能DA转换)
IIC_WaitAck();//等待PCF8591反馈
IIC_Start();//发送开启信号
IIC_SendByte(0x91);//选择PCF8591芯片,确定读的模式
IIC_WaitAck();//等待PCF8591反馈
temp = IIC_RecByte();//接收数据
IIC_SendAck(1);//选择不应答
IIC_Stop();//停止发送
return temp;
}
//入口参数:要进行转换的数值
//返回值:无
//函数功能:对入口参数要转换的DA数据进行转换
void Pcf8591_Dac(unsigned char trans_dat)
{
IIC_Start();//发送开启信号
IIC_SendByte(0x90);//选择PCF8591芯片,确定写的模式
IIC_WaitAck();//等待PCF8591反馈
IIC_SendByte(0x41);//使能DA转换(随便写通道编号,不影响,主要的功能是使能DA)
IIC_WaitAck();//等待PCF8591反馈
IIC_SendByte(trans_dat);//将待转换的数据发送出去
IIC_WaitAck();//等待PCF8591反馈
IIC_Stop();//停止发送
}
//入口参数:需要写入的字符串,写入的地址(务必为8的倍数),写入数量
//返回值:无
//函数功能:向EERPOM的某个地址写入字符串中特定数量的字符。
void EEPROM_Write(unsigned char* EEPROM_String, unsigned char addr, unsigned char num)
{
IIC_Start();//发送开启信号
IIC_SendByte(0xA0);//选择EEPROM芯片,确定写的模式
IIC_WaitAck();//等待EEPROM反馈
IIC_SendByte(addr);//写入要存储的数据地址
IIC_WaitAck();//等待EEPROM反馈
while(num--)
{
IIC_SendByte(*EEPROM_String++);//将要写入的信息写入
IIC_WaitAck();//等待EEPROM反馈
IIC_Delay(200);
}
IIC_Stop();//停止发送
}
//入口参数:读到的数据需要存储的字符串,读取的地址(务必为8的倍数),读取的数量
//返回值:无
//函数功能:读取EERPOM的某个地址中的数据,并存放在字符串数组中。
void EEPROM_Read(unsigned char* EEPROM_String, unsigned char addr, unsigned char num)
{
IIC_Start();//发送开启信号
IIC_SendByte(0xA0);//选择EEPROM芯片,确定写的模式
IIC_WaitAck();//等待EEPROM反馈
IIC_SendByte(addr);//写入要读取的数据地址
IIC_WaitAck();//等待EEPROM反馈
IIC_Start();//发送开启信号
IIC_SendByte(0xA1);//选择EEPROM芯片,确定读的模式
IIC_WaitAck();//等待EEPROM反馈
while(num--)
{
*EEPROM_String++ = IIC_RecByte();//将要写入的信息写入
if(num) IIC_SendAck(0);//发送应答
else IIC_SendAck(1);//不应答
}
IIC_Stop();//停止发送
}
# include "STC15F2K60S2.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);
//函数名:ADC转换函数
//入口参数:要进行转换的通道控制位
//返回值:ADC转换的数值
//函数功能:对指定的通道进行ADC转换,函数返回转换的数值
unsigned char Pcf8591_Adc(unsigned char channel_num_contrl);
//函数名:DAC转换函数
//入口参数:要进行转换的数值
//返回值:无
//函数功能:对入口参数要转换的DA数据进行转换
void Pcf8591_Dac(unsigned char trans_dat);
//函数名:写EEPROM函数
//入口参数:需要写入的字符串,写入的地址(务必为8的倍数),写入数量
//返回值:无
//函数功能:向EERPOM的某个地址写入字符串中特定数量的字符。
void EEPROM_Write(unsigned char* EEPROM_String, unsigned char addr, unsigned char num);
//函数名:读EEPROM函数
//入口参数:读到的数据需要存储的字符串,读取的地址(务必为8的倍数),读取的数量
//返回值:无
//函数功能:读取EERPOM的某个地址中的数据,并存放在字符串数组中。
void EEPROM_Read(unsigned char* EEPROM_String, unsigned char addr, unsigned char num);
/*头文件声明区*/
#include
#include
#include
#include
#include
#include "iic.h"
/* 变量声明区 */
unsigned char Key_Val,Key_Old,Key_Down,Key_Up;
unsigned char Seg_Pos;
unsigned char Key_Slow_Down;
unsigned char Seg_Slow_Down;
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0};
unsigned char ucLed[8] ={0,0,0,0,0,0,0,0};
unsigned char dat[2] = {30,60};
unsigned char a = 200;//int型会溢出,要使用必须把高位和低位拆开
/*键盘处理函数*/
void Key_Proc()
{
if(Key_Slow_Down)return;
Key_Slow_Down = 1;
Key_Val = Key_Read();
Key_Down = Key_Val & (Key_Val ^ Key_Old);
Key_Up = ~Key_Val & (Key_Val ^ Key_Old);
Key_Old = Key_Val;
switch(Key_Down)
{
case 19:
//dat[0] -= 10;
a += 10;
break;
case 18:
dat[1] -= 10;
break;
case 17:
EEPROM_Write(dat,0,2);
break;
case 16:
EEPROM_Write(&a,0,1);
break;
}
}
/*信息处理函数*/
void Seg_Proc()
{
if(Seg_Slow_Down)return;
Seg_Slow_Down = 1;
//
// Seg_Buf[0] = dat[0] / 10;
// Seg_Buf[1] = dat[0] % 10;
//
// Seg_Buf[6] = dat[1] / 10;
// Seg_Buf[7] = dat[1] % 10;
Seg_Buf[0] = a / 100 % 10;
Seg_Buf[1] = a / 10 % 10;
Seg_Buf[2] = a % 10;
Seg_Buf[6] = dat[1] / 10;
Seg_Buf[7] = dat[1] % 10;
}
/*其他函数*/
void Led_Proc()
{
Beep(1);
}
(这个可以使用STC的定时器计算那里生成c代码,后面要自己添加ET0,EA打开中断)
/*定时器0初始化函数*/
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
(为了定时执行特定的任务,如此处设置了定时的时间触发了数码管和LED产生特定反应)
/*定时器0中断服务函数*/
void Timer0Server() interrupt 1
{
if(++Key_Slow_Down == 10)Key_Slow_Down = 0;
if(++Seg_Slow_Down == 500)Seg_Slow_Down = 0;
if(++Seg_Pos == 8)Seg_Pos = 0;
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
}
void main()
{
//EEPROM_Read(dat,0,2);
//EEPROM_Read(&a,0,1);//单变量要用&
EEPROM_Read(&a,0,1);
Sys_Init();
Timer0Init();
while(1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}
这里的应用在内在结构是2k的,需要注意。
主要使用这个2k的就行,根据前面的信息可以知道A2-0都是接地为0,最后一位是0还是1,主要看我们是读还是写来修改。根据这个二进制转换为0xA0或0xA1,即为读这个芯片或写这个芯片。
有两种方式写入,每一页之内写8个字节,尽量从第0位,即最低位开始写。
三个入口参数,第二个参数传入的地址一定要是8的倍数,第三个参数为写入数据的数量,最好也是8的倍数。A0为写的模式
这也是有两种方式读取
一页最多只能写8个字节,这些是写入的类型所占的字节数