蓝桥杯单片机编程笔记Word文档下载推荐.docx
《蓝桥杯单片机编程笔记Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《蓝桥杯单片机编程笔记Word文档下载推荐.docx(41页珍藏版)》请在冰豆网上搜索。
P0=0xff;
P2=P2&
0x1f;
//位选
0x1f)|0xc0);
P0=(1<
<
dspcom);
//段码输入
P0=tab[dspbuf[dspcom]];
if(++dspcom==8)
dspcom=0;
}
注意:
这里1左移dspcom位,刚开始dspcom=0,则1左移dspcom位依旧为1,接着dspcom每次自增1,1对应二进制00000001,即把1每次向左移,每次都比上一次多移一位,直至8位移完,对应8个数码管。
定时器配置:
这里只需记住定时器的配置,知道怎么使用就可以了。
首先有两个定时器,T0和T1,(也有的单片机有T2),定时器有4种工作方式0,1,2,3;
其中最常用的是方式1(16位),其次是方式2(8位自动重装,串口通讯中断会用到)。
定时器需要配置:
TMOD|=0x01;
配置成使用定时器0,工作方式为1;
同理使用定时器1工作方式1:
TMOD|=0x10;
则同时使用两个定时器且工作方式为1,那么可以:
TMOD|=0x11;
定时器1配置成工作方式2:
TMOD|=0x20;
接着配置(以定时器0举例):
TH0=(65535-2000)/256;
//配置初值
TL0=(65535-2000)%256;
ET0=1;
TR0=1;
//定时0中断
EA=1;
//总中断
定时器1也是同理的,只不过0要改成1.
接着定时中断函数和优先级:
定时器0
voidisr_timer_0(void)interrupt1//默认中断优先级1
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
//定时器重载
display();
定时器1:
voidisr_timer_1(void)interrupt3//默认中断优先级3
定时器0优先级为1,定时器1为3,串口中断优先级为4,总共有5个中断源,后面还会介绍外部中断和串口中断。
数码管动态扫描,显示函数放在定时中断函数里面,2ms扫一次是最稳定的!
!
三、矩阵键盘
矩阵键盘需要死记了!
这里不再讲独立键盘。
第二种单片机键盘扫描代码(没有消抖):
sfrP4^4=0xC0;
//键盘定义
sbitr1=P3^0;
//4行
sbitr2=P3^1;
sbitr3=P3^2;
sbitr4=P3^3;
//4列
sbitc1=P4^4;
sbitc2=P4^2;
sbitc3=P3^5;
sbitc4=P3^4;
//读取矩阵键盘键值
unsignedcharkey_scan()
unsignedcharkey_value;
r1=0;
r2=r3=r4=1;
c1=c2=c3=c4=1;
if(!
c1)key_value=0;
elseif(!
c2)key_value=1;
c3)key_value=2;
c4)key_value=3;
r2=0;
r1=r3=r4=1;
c1)key_value=4;
c2)key_value=5;
c3)key_value=6;
c4)key_value=7;
r3=0;
r2=r1=r4=1;
c1)key_value=8;
c2)key_value=9;
c3)key_value=10;
c4)key_value=11;
r4=0;
r2=r3=r1=1;
c1)key_value=12;
c2)key_value=13;
c3)key_value=14;
c4)key_value=15;
returnkey_value;
四、串口通讯和串口中断
串口中断配置只需记住几个寄存器就行了,
初始化:
SCON=0x50;
//串口配置成模式1
//定时器1,方式2,8位自动重装
TH1=256-(unsigbedchar)(SYSTEMCLOK/BAUDRATE/384+0.5);
//定时初值
ES=1;
//串口中断打开
TR1=1;
//启动定时器1
EA=1;
//总中断打开
这里必须使用定时器1,不能用定时器0.
下面是模块化的函数:
voidUart_Init()
SCON=0x50;
TMOD|=0x20;
TH1=256-(SYSREMCLOCK/BAUDRATE/384+0.5);
ES=1;
TR1=1;
EA=1;
voidUartSend(unsignedchar*pBuff,intlength)
unsignedcharc;
inti=0;
for(i=0;
i<
length;
i++)
c=pBuff[i];
SBUF=c;
while(TI==0);
TI=0;
接收数据可以这样写:
定义全局变量:
unsignedcharuart_buf[100];
//串口缓冲区
unsignedintuart_Count=0;
//串口数据长度
voiduart_inte()interrupt4
unsignedcharc;
if(RI)
{
RI=0;
c=SBUF;
uart_buf[uart_Count]=c;
uart_Count++;
}
如果可以指定的接收,可以这样写
//串口中断服务函数
voidisr_uart(void)interrupt4{
if(RI){
RI=0;
//清除接收标志位
rxbuf[rxcnt]=SBUF;
if(rxbuf[rxcnt]=='
\n'
){
rxcnt=0;
rx_over=1;
ES=0;
//回车为接收结束标志,检测到回车符后,关闭串口中断
}
else{
rxcnt++;
}
}
当接收完一帧数据时关闭串口中断,设一个标志位,处理完之后再打开。
#include"
reg51.h"
intrins.h"
typedefunsignedcharBYTE;
typedefunsignedintWORD;
BYTEcode_tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
chararry[10]="
ICANPLAY"
;
unsignedcharx;
#defineFOSC11059200//12000000L//系统频率
#defineBAUD115200//串口波特率
#defineNONE_PARITY0//无校验
#defineODD_PARITY1//奇校验
#defineEVEN_PARITY2//偶校验
#defineMARK_PARITY3//标记校验
#defineSPACE_PARITY4//空白校验
#definePARITYBITNONE_PARITY//定义校验位
sfrAUXR=0x8e;
//辅助寄存器
sfrP_SW1=0xA2;
//外设功能切换寄存器1
#defineS1_S00x40//P_SW1.6
#defineS1_S10x80//P_SW1.7
sbitP22=P2^2;
bitbusy;
voidSendData(BYTEdat);
voidSendString(char*s);
voidmain()
ACC=P_SW1;
ACC&
=~(S1_S0|S1_S1);
//S1_S0=0S1_S1=0
P_SW1=ACC;
//(P3.0/RxD,P3.1/TxD)
//ACC=P_SW1;
//ACC&
//S1_S0=1S1_S1=0
//ACC|=S1_S0;
//(P3.6/RxD_2,P3.7/TxD_2)
//P_SW1=ACC;
//
//S1_S0=0S1_S1=1
//ACC|=S1_S1;
//(P1.6/RxD_3,P1.7/TxD_3)
//#if(PARITYBIT==NONE_PARITY)
//8位可变波特率
//#elif(PARITYBIT==ODD_PARITY)||(PARITYBIT==EVEN_PARITY)||(PARITYBIT==MARK_PARITY)
//SCON=0xda;
//9位可变波特率,校验位初始为1
//#elif(PARITYBIT==SPACE_PARITY)
//SCON=0xd2;
//9位可变波特率,校验位初始为0
//#endif
AUXR=0x40;
//定时器1为1T模式
TMOD=0x20;
//定时器1为模式2(8位自动重载)
TL1=(256-(FOSC/32/BAUD));
//设置波特率重装值
TH1=(256-(FOSC/32/BAUD));
TR1=1;
//定时器1开始工作
ES=1;
//使能串口中断
EA=1;
while
(1)
//SendString(arry);
SendString("
ICANPLAY~~\r\n"
);
//上位机显示接收文本模式
//SendData(x);
/*----------------------------
UART中断服务程序
-----------------------------*/
voidUart()interrupt4using1
if(RI)//单片机接收数据,发送数字0~9,可在数码管上显示,发送hex模式
//清除RI位
//P0=SBUF;
x=SBUF;
//将缓存器的数据赋值给x
P0=0xff;
//消隐
P2|=0xe0;
P2&
=0x1f;
P0=code_tab[x];
//段选
P0=0x01;
//位选第一位
P2|=0xc0;
=0x3f;
if(TI)
TI=0;
//清除TI位
busy=0;
//清忙标志
发送串口数据
----------------------------*/
voidSendData(BYTEdat)
while(busy);
//等待前面的数据发送完成
ACC=dat;
//获取校验位P(PSW.0)
if(P)//根据P来设置校验位
#if(PARITYBIT==ODD_PARITY)
TB8=0;
//设置校验位为0
#elif(PARITYBIT==EVEN_PARITY)
TB8=1;
//设置校验位为1
#endif
else
busy=1;
SBUF=ACC;
//写数据到UART数据寄存器
发送字符串
voidSendString(char*s)
while(*s)//检测字符串结束标志
SendData(*s++);
//发送当前字符
记不住可以看手册!
#defineFOSC11059200L
#defineBAUD115200
sfrAUXR=0x8e;
sbitP22=P2^2;
SCON=0x50;
AUXR=0x40;
//设置定时器T1为1T,即一个机器周期模式
TMOD=0x20;
TL1=(256-(FOSC/32/BAUD));
TH1=(256-(FOSC/32/BAUD));
Hello"
while
(1);
P0=SBUF;
if(TI)
TI=0;
busy=0;
while(busy);
busy=1;
SBUF=dat;
while(*s)
SendData(*s++);
五、外部中断的使用
#include<
reg52.h>
sbitL1=P0^0;
intmain(){
IT0=1;
//IT0=1,下降沿触发外部中断0,IT0=0边沿触发
EX0=1;
//使用外部中断0
while
(1){
voidEx_int0()interrupt0//外部中断优先级最高
0x1f)|0x80);
L1=~L1;
P2=(P2&
0x1f);
}
其中,外部中断的引脚控制是P3^2,P3^3,即对应独立按键的S5,S4。
六、实时时钟DS1302的使用
蓝桥杯提供函数,解释为:
里面的命令和写入的数据可以看芯片手册:
左侧的READ、WRITE分别是读写的命令,BIT7-BIT0是要写入的数据,根据需要进行配置。
DS1302只需记住这两个函数即可:
Write_Ds1302(,)与Read_Ds1302(x),配置看手册。
重点:
芯片表说明:
第一行:
秒->
因为秒的围是0-59,所以6,5,4位表示秒的十位,3,2,1,0表示个位,十位最大是5,所以三位即可。
第二行:
跟上面一样;
第三行:
7位:
1为12小时制,0为24小时制;
5位:
12小时制时为0表示上午,1表示下午,24小时制时,和4位一起表示小时的十位;
其余的时间一样的表示。
倒数第二行:
只看7位:
为1时禁止写数据,所以开始写数据时必须置0;
读数时:
需要加“写操作这一行代码”。
读的话直接按照命令读即可。
DS1302进阶(BCD码转换):
解决之前60秒不能进位的问题。
1)写入初始值时,要把10十进制数转换为BCD码,
例:
写入时间->17:
58:
50
Ds1302_Single_Byte_Write(0x8e,0x00);
//写操作
Ds1302_Single_Byte_Write(0x85,((17/10)<
4|(17%10)));
//写时
Ds1302_Single_Byte_Write(0x83,((58/10)<
4|(58%10)));
//写分
Ds1302_Single_Byte_Write(0x81,((50/10)<
4|(50%10)));
//写秒
Ds1302_Single_Byte_Write(0x8e,0x80);
//写保护
即转换的公式是:
((Value/10)<
4|(Value%10)),可以写一个settime()函数。
2)读数:
读回来的数要进行转换成十进制数
((ReadValue&
0x70)>
>
4)*10+(ReadValue&
0x0F);
八进制转十进制->
ReadValue=Ds1302_Single_Byte_Read(0x85);
hour=((ReadValue&
!
(这句一定不要省)Ds1302_Single_Byte_Write(0x00,0x00);
ReadValue=Ds1302_Single_Byte_Read(0x83);
minute=((ReadValue&
Ds1302_Single_Byte_Write(0x00,0x00);
ReadValue=Ds1302_Single_Byte_Read(0x81);
sec=((ReadValue&
显示:
dspbuf[0]=hour/10;
dspbuf[1]=hour%10;
dspbuf[2]=minute/10;
dspbuf[3]=minute%10;
dspbuf[4]=sec/10;
dspbuf[5]=sec%10;
七、PCF8591与IIC总线的使用
(1)IIC总线的使用:
比赛提供了IIC的两个库文件,IIC.h;
IIC.c,其中需要注意的函数是:
其中,该函数是初始化的,当使用AD转换的时候需要在main函数开始时调用,该函数部只需看这句代码即可:
i2c_sendbyte(0x03);
//ADC通道3,板上有4个模拟输入口,分别为0,1,2,3;
设置哪一个模拟输入口就是根据这句代码,0x03表示通道3,这是根据芯片手册配置的,如图:
8位前6位不用管,都为0,最后两位就是配置选择哪一个通道的。
第二个函数:
读取AD转换后的数值,这个函数直接调用就可以了,函数部如何实现不用管,但是需要注意的是:
该函数扫描调用最好是100ms。
第三个函数,上面的都是AD转换,即模拟信号转数字信号,下面这个函数是DA转换,数字信号转换成模拟信号,就是单片机输出数字信号,用万能表去量单片机引出的引脚,量一下电压大小,这个估计比赛不会考,不过预防万一:
该函数和上面两个函数分离开来的,一、二函数是要在一起使用,初始化后之后才能调用,第三个加入头文件,直接调用即可,比较简单!
!
上面说法有误,A/D转换的初始化函数和读取转换后的数值都需要自己写。
这里了解一下PCF8591只需根据时序格式发送地址字节和控制字节:
,这是地址字节,其中A2,A1,A0硬件已经接地,故都为0,最低位表示的是你要从IIC总线上读数还是写数据,1表示读,0表示写,即读数据发的地址是:
0x91;
写数据发的地址是0x90;
控制字节:
由芯片资料知,控制字节有8位,有两位固定是0,除了第0、1位需要自己设置,其他的我们都设为0,那些位都是一些具体的功能,我们暂时用不着,不用管先,第0、1位是模拟通道选择,PCF8591上提供了4路模拟通道,根据需求进行选择,如选择通道3即发送控制字节:
0x03;
地址字节和控制字节都明白了,接下来根据时序要求进行配置,A/D转换