蓝桥杯笔记
1. 基础模块调用模板
#include
//#include
#define uchar unsigned char
#define uint unsigned int
uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xbf,0xff};
uchar yi,er,san,si,wu,liu,qi,ba;
uchar num;
void delayms(int ms)
{
int i,j;
for(i=0;i0;j--);
}
void Allinit()
{
P2=0xA0;
P0=0x00;
P2=0x80;
P0=0xFF;
P2=0xC0;
P0=0xFF;
P2=0xFF;
P0=0xFF;
}
//void allinit(void)
//{
// P2|=0xA0;
// P2&=0xBF;
// P0=0x00;//关闭蜂鸣器,继电器
//
// P2|=0x80;
// P2&=0x9F;
// P0=0xFF;//关闭LED灯
//
// P2|=0xC0;//打开位选573 U8
// P2&=0xDF;
// P0=0xFF;//选择所有数码管
// P2|=0xE0;//打开位选573 U7
// P2&=0xFF;
// P0=0xFF;//关闭所有数码管
//}
void display1(uchar yi,uchar er,uchar san,uchar si)
{
P2=0xC0;
P0=0x01;
P2=0xFF;
P0=tab[yi];
delayms(1);
P2=0xC0;
P0=0x02;
P2=0xFF;
P0=tab[er];
delayms(1);
P2=0xC0;
P0=0x04;
P2=0xFF;
P0=tab[san];
delayms(1);
P2=0xC0;
P0=0x08;
P2=0xFF;
P0=tab[si];
delayms(1);
}
void display2(uchar wu,uchar liu,uchar qi,uchar ba)
{
P2=0xC0;
P0=0x10;
P2=0xFF;
P0=tab[wu];
delayms(1);
P2=0xC0;
P0=0x20;
P2=0xFF;
P0=tab[liu];
delayms(1);
P2=0xC0;
P0=0x40;
P2=0xFF;
P0=tab[qi];
delayms(1);
P2=0xC0;
P0=0x80;
P2=0xFF;
P0=tab[ba];
delayms(1);
}
void keyscan16(void)
{
uchar temp;
P44=0;P42=1;P3=0x7F;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
delayms(5);
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0x7e: num=0; break;
case 0x7d: num=1; break;
case 0x7b: num=2; break;
case 0x77: num=3; break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
}
}
P44=1;P42=0;P3=0xBF;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
delayms(5);
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xbe: num=4; break;
case 0xbd: num=5; break;
case 0xbb: num=6; break;
case 0xb7: num=7; break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
}
}
P44=1;P42=1;P3=0xDF;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
delayms(5);
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xde: num=8; break;
case 0xdd: num=9; break;
case 0xdb: num=10; break;
case 0xd7: num=11; break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
}
}
P44=1;P42=1;P3=0xEF;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
delayms(5);
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xee: num=12; break;
case 0xed: num=13; break;
case 0xeb: num=14; break;
case 0xe7: num=15; break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
}
}
}
void main(void)
{
Allinit();
while(1)
{
//keyscan();
keyscan16();
display1(yi,er,san,si);
display2(wu,liu,qi,ba);
}
}
2. 官方驱动模块改写
2.1 onewire (DS18b20)
官方onewire.c
#include "reg52.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
while(t--);
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
改写onewire(ds18b20)
//1. 头文件修改(#include ,#include "onewire.h")
//2. 所有调用Delay_OneWire()函数内地参数后面加个0(扩大十倍)
//3. 编写获取温度地函数Tempget() (数值为整数)
unsigned char Tempget(void)
{
unsigned char low,high,temp;
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
low=Read_DS18B20();
high=Read_DS18B20();
temp=high<<4;
temp|=(low>>4);
return temp;
}
//4.温度含小数点的情况
long Tempget(void) //(返回为温度值*10000)25.0625
{
long high,low,temp;
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
Delay_OneWire(200);
low=Read_DS18B20();
high=Read_DS18B20();
temp=((high&0x0F)<<8)|low;
temp=temp*625;
return temp;
}
//4.onewire.h中添加 unsigned char Tempget(void);主函数头文件调用
2.2 ds1302
官方ds1302.c
#include
#include
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
改写ds1302
//1. 头文件修改
//2. 每一组__nop__();函数增加为8到10个
//3. 改写写入函数Write_Ds1302_Byte (十进制转十六进制)
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
SCK=0; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
RST=1; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
Write_Ds1302(address);
Write_Ds1302((dat/10<<4)|(dat%10));
RST=0;
}
//4.改写读取函数Read_Ds1302_Byte (十六进制转十进制)
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,dat1,dat2,temp=0x00;
RST=0; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
SCK=0; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
RST=1; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
SCK=0; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
SCK=1; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
SDA=0; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
SDA=1; _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_();
dat1=temp/16;
dat2=temp%16;
temp=dat1*10+dat2;
return (temp);
}
//5.创建初始时间数据
//初始化和获取函数在主函数内时uchar shijian[7]={55,59,23,0,0,0,0};
//主函数调用驱动函数时extern unsigned char shijian[];
//6.时间数据初始化写入函数DS_init()
void DS_init(void)
{
uchar i,add;
add=0x80;
Write_Ds1302_Byte(0x8E,0x00);
for(i=0;i<7;i++)
{
Write_Ds1302_Byte(add,shijian[i]);
add=add+2;
}
Write_Ds1302_Byte(0x8E,0x80);
}
//7.时间数据初始化读取函数DS_get()
void DS_get(void)
{
uchar i,add;
add=0x81;
Write_Ds1302_Byte(0x8E,0x00);
for(i=0;i<7;i++)
{
shijian[i]=Read_Ds1302_Byte(add);
add=add+2;
}
Write_Ds1302_Byte(0x8E,0x80);
}
//8.ds1302.h文件中相应修改,主函数头文件调用
2.3 iic (IIC和EEPROM)
官方iic.c
#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;
}
改写iic
//1. 头文件修改;延时适当加长
//2. 可删除IIC_SendAck函数;IIC_RecByte函数按需取舍
//3.按需选取以下四个功能函数
// 3.1 数字信号转模拟信号输出 本开发板只需要写0x40
void DA_write(unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
// 3.2 模拟信号转数字信号读取
// 地址对应关系 0x00-Ain0-外接插针;0x01-Ain1-光敏检测RD1;0x02-Ain2-放大器输出;0x03-Ain3-电位器Rb2
// 255一般对应5V可以乘以0.39按照100划分,也可以乘以1.96按500划分(变为int型)
unsigned char AD_read(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
temp=temp*0.39;
return temp;
}
// 3.3 EEPROM读取数据
unsigned char EEPROM_read(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xA0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xA1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
// 3.4 EEPROM存储数据
void EEPROM_write(unsigned char add,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xA0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
3. 国赛重要模块
3.1 超声波
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();}
sbit TX = P1^0; //发射引脚
sbit RX = P1^1; //接收引脚
unsigned int intr = 0;
bit s_flag;
unsigned int t = 0;
unsigned int distance;
void dist_get(void)
{
if(s_flag) // 200毫秒更新一次数据
{
s_flag = 0;
send_wave(); //发送方波信号
TR1 = 1; //启动计时
while((RX == 1) && (TF1 == 0)); //等待收到脉冲
TR1 = 0; //关闭计时
if(TF1 == 1)//发生溢出
{
TF1 = 0;
distance = 9999; //无返回
}
else
{
t = TH1;// 计算时间
t <<= 8;
t |= TL1;
distance = (unsigned int)(t*0.017); //计算距离
distance = distance/12;
//t*340 // t/1000000*340/2*100
}
TH1 = 0;
TL1 = 0;
}
liu = distance/100;
qi = distance%100/10;
ba = distance%10;
}
void Timer0Init(void) //2毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x9A; //设置定时初值
TH0 = 0xA9; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Timer1Init(void) //2毫秒@11.0592MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
}
//定时器0中断服务函数
void isr_timer_0(void) interrupt 1 //默认中断优先级 1
{
TL0 = 0x9A; //设置定时初值
TH0 = 0xA9; //设置定时初值
if(++intr == 100)
{
s_flag = 1;
intr = 0;
}
}
//TX引脚发送40KHz方波信号驱动超声波发送探头
//使用软件延时注意RC振荡器频率
void send_wave(void)
{
unsigned char i = 8; //发送8个脉冲
do
{
TX = 1;
somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;
TX = 0;
somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;
}
while(i--);
}
3.2 串口通信
uchar flag,num;
unsigned char txbuffer1[] = "IAP15F2 USART TEST PROGRAMrn";
unsigned char enter[] = {"rn"};
void ser() interrupt 4 //串口中断
{
RI=0;
num=SBUF;
if(num=='$')
{
P2=0x80; P0=0x55;
}
}
void uart_tx(unsigned char *p,unsigned char length)
{
unsigned char i;
for(i=0;i
SBUF = *(p+i);
while(TI == 0);
TI = 0;
}
}
void send(unsigned char *p)
{
unsigned char index=0;
do
{
SBUF=p[index++];
while(TI == 0);
TI = 0;
}
while(p[index]!=0);
}
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T//0100 0000
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器//111 1110
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xE0; //设定定时初值
TH1 = 0xFE; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
//调用例
//uart_tx(enter,4);
//send(txbuffer1);
4. 常用功能
4.1 LED灯控制
控制单个LED灯
//例
P2=0x80;
P0=0xFE;//点亮L1
P2=0x80;
P0=0xFF;//熄灭L1
多控不冲突
unsigned char LED_Bit=0xFF;
#define LED1_ON P2|=0x80;P2&=0x9F; LED_Bit&=0xFE; P0=LED_Bit;
#define LED1_OFF P2|=0x80;P2&=0x9F; LED_Bit|=0x01; P0=LED_Bit;
#define LED2_ON P2|=0x80;P2&=0x9F; LED_Bit&=0xFD; P0=LED_Bit;
#define LED2_OFF P2|=0x80;P2&=0x9F; LED_Bit|=0x02; P0=LED_Bit;
#define LED3_ON P2|=0x80;P2&=0x9F; LED_Bit&=0xFB; P0=LED_Bit;
#define LED3_OFF P2|=0x80;P2&=0x9F; LED_Bit|=0x04; P0=LED_Bit;
#define LED4_ON P2|=0x80;P2&=0x9F; LED_Bit&=0xF7; P0=LED_Bit;
#define LED4_OFF P2|=0x80;P2&=0x9F; LED_Bit|=0x08; P0=LED_Bit;
#define LED5_ON P2|=0x80;P2&=0x9F; LED_Bit&=0xEF; P0=LED_Bit;
#define LED5_OFF P2|=0x80;P2&=0x9F; LED_Bit|=0x10; P0=LED_Bit;
#define LED6_ON P2|=0x80;P2&=0x9F; LED_Bit&=0xDF; P0=LED_Bit;
#define LED6_OFF P2|=0x80;P2&=0x9F; LED_Bit|=0x20; P0=LED_Bit;
#define LED7_ON P2|=0x80;P2&=0x9F; LED_Bit&=0xBF; P0=LED_Bit;
#define LED7_OFF P2|=0x80;P2&=0x9F; LED_Bit|=0x40; P0=LED_Bit;
#define LED8_ON P2|=0x80;P2&=0x9F; LED_Bit&=0x7F; P0=LED_Bit;
#define LED8_OFF P2|=0x80;P2&=0x9F; LED_Bit|=0x80; P0=LED_Bit;
4.2 蜂鸣器控制
P2=0xA0;
P0=0x40;
4.3 中断优先级
4.4 频率采集*
long intr=0,freq; //全局变量
void Timer2Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x20; //设置定时初值
T2H = 0xD1; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04; //开定时器2中断
EA=1;
}
void Timer0Init(void) //计数模式
{
AUXR |= 0x80;
TMOD = 0x05;
TL0=0;
TH0=0;
TR0=1;
}
void timer2int() interrupt 12 //中断入口
{
intr++;
if(intr==999)
{
intr=0;
freq=(TH0<<8)|TL0;
TL0=0;TH0=0;
}
}
void Timer0Init(void) //5微秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xC4; //设置定时初值
TH0 = 0xFF; //设置定时初值
TF0 = 0; //清除TF0标志
}
void Timer0_Rountine(void) interrupt 1
{
if(P34==0)
{
zheng++;
if(t_flag==1)
{
t_flag=0;
fan_now=fan;
fan=0;
}
}
else if(P34==1)
{
fan++;
if(t_flag==0)
{
t_flag=1;
zheng_now=zheng;
zheng=0;
}
}
// if(P34==0)
// {
// if(high==1)
// {
// time=num_p;
// num_p=0;
// high=0;
// }
// num_p++;
// }
// else if(P34==1)
// {
// num_p++;
// high=1;
// }
}
void Timer1Init(void) //2毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x40; //设置定时初值
TH1 = 0xA2; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
}
void Timer1_Rountine(void) interrupt 3
{
if(pinlv==1)
{
intr++;
if(intr==495)
{
TR0=1;ET0 = 1;
}
else if(intr== 500)
{
intr = 0;
TR0=0;ET0 = 0;
}
}
}
4.5 PWM波
//例程pre7
uchar mode=1;
uchar Time=0;
uchar tt=0;
uint miao=0;
void Timer0Init(void) //100微秒@11.0592MHz // 10
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xAE; //设置定时初值
TH0 = 0xFB; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
}
void timer0() interrupt 1
{
tt++;miao++;
if(tt==11)tt=1;
if(Time>0)
{
if(mode==1)
{
if(tt<3)P34=1;
else P34=0;
}
else if(mode==2)
{
if(tt<4)P34=1;
else P34=0;
}
else if(mode==3)
{
if(tt<8)P34=1;
else P34=0;
}
}
if(miao==10000)
{
miao=0;
if(Time>0)Time--;
}
}
4.6 彩灯控制
- 思想参考PWM波控制
- 可在定时器中控制以达到更好的效果