单片机程序知识点.docx

上传人:b****5 文档编号:7545459 上传时间:2023-01-24 格式:DOCX 页数:23 大小:430.84KB
下载 相关 举报
单片机程序知识点.docx_第1页
第1页 / 共23页
单片机程序知识点.docx_第2页
第2页 / 共23页
单片机程序知识点.docx_第3页
第3页 / 共23页
单片机程序知识点.docx_第4页
第4页 / 共23页
单片机程序知识点.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

单片机程序知识点.docx

《单片机程序知识点.docx》由会员分享,可在线阅读,更多相关《单片机程序知识点.docx(23页珍藏版)》请在冰豆网上搜索。

单片机程序知识点.docx

单片机程序知识点

单片机程序知识点

按键扫描支持连续按一般思路

u8KEY_Scan(void)

{

if(KEY按下)

{

delay_ms(10);//延时10-20ms,防抖。

if(KEY确实按下)returnKEY_Value;

return无效值;

}

}

按键扫描不支持连续按一般思路

u8KEY_Scan(void)

{

staticu8key_up=1;

if(key_up&&KEY按下)

{

delay_ms(10);//延时,防抖

key_up=0;//标记这次key已经按下

if(KEY确实按下)

{

returnKEY_VALUE;

}

}elseif(KEY没有按下)key_up=1;

return没有按下

}

串口通讯2

voidUART()interrupt4

{

if(RI)//检测是否接收完成

{

num=SBUF;//num取出接收缓存器的值

P1=SBUF;

num++;

RI=0;

SBUF=num;

while(!

TI);

TI=0;}}

 

两个等于控制占空比

timer0()interrupt1

{

t++;//每次定时器溢出加1

if(t==250)//PWM周期100个单位

{

t=0;//使t=0,开始新的PWM周期

P1=0x00;//输出端口

}

//按照当前占空比切换输出为高电平

if(PWM_T==t)

{

P1=0xff;

}}

数码管动态显示

unsignedcharcodeDuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示段码值0~F

unsignedcharcodeWeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};/分别对应相应的数码管点亮,即位码

while

(1)

{

DataPort=WeiMa[i];//取位码

LATCH2=1;//位锁存

LATCH2=0;

//取显示数据,段码

DataPort=DuanMa[num+i];

LATCH1=1;//段锁存

LATCH1=0;

//扫描间隙延时,时间太长会闪烁,太短会造成重影

Delay(200);

i++;

//检测8位扫描完全结束?

如扫描完成则从第一个开始再次扫描8位

if(8==i)i=0;

}

数码管动态显示

/*------------------------------------------------

显示函数,用于动态扫描数码管

输入参数FirstBit表示需要显示的第一位,如赋值2表示从第三个数码管开始显示,如输入0表示从第一个显示。

Num表示需要显示的位数,如需要显示99两位数值则该值输入2

------------------------------------------------*/

//存储显示值的数组

unsignedcharTempData[10];

//分解显示信息,如要显示68,

则68/10=668%10=8

TempData[0]=dofly_DuanMa[num/10];

TempData[1]=dofly_DuanMa[num%10];

voidDisplay(unsignedcharFirstBit,unsignedcharNum)

{

unsignedchari;

for(i=0;i

DataPort=0;//清空数据,防止有交替重影

LATCH1=1;//段锁存

LATCH1=0;

DataPort=WeiMa[i+FirstBit];//取位码

LATCH2=1;//位锁存

LATCH2=0;

DataPort=TempData[i];//取显示数据,段码

LATCH1=1;//段锁存

LATCH1=0;

Delay(200);//扫描间隙延时,时间太长/会闪烁,太短会造成重影

}

}

 

动态显示消隐方法

if(num<1000)//如果小于1000则千位不显示

TempData[0]=0;

elseTempData[0]=dofly_DuanMa[num/1000];

//分解显示信息,如要显示68,则68/10=6/68%10=8

//如果小于100则千位和百位都不显示

if(num<100)TempData[1]=0;

else

TempData[1]=dofly_DuanMa[(num%1000)/100];

//如果小于10,则千位、百位和十位

/都不显示

if(num<10)TempData[2]=0;

else

TempData[2]=dofly_DuanMa[((num%1000)%100)/10];

使用中断实现分频器的功能

/*------------------------------------------------

定时器中断子程序

------------------------------------------------*/

voidTimer0_isr(void)interrupt1using1

{

staticunsignedchari;

//重新赋值12M晶振计算,指令周期1uS,500x2=1mS方波

TH0=(65536-500)/256;

TL0=(65536-500)%256;

i++;

P1=i;

/*P1口8路输出不同频率,相当于一个分频器,高频用示波器测量,低频可以直接用led观测P1.0输出1ms方波,P1.1输出2ms,p1.2输出4ms,以此类推*/

}

 

按键行扫描程序

/*------------------------------------------------

按键扫描函数,返回扫描键值

------------------------------------------------*/

//键盘扫描函数,使用行列逐级扫描法

unsignedcharKeyScan(void)

{

unsignedcharVal;

KeyPort=0xf0;//高四位置高,低四位拉低

if(KeyPort!

=0xf0)//表示有按键按下

{

DelayMs(10);//去抖

if(KeyPort!

=0xf0)//表示有按键按下

{

KeyPort=0xfe;//检测第一行

if(KeyPort!

=0xfe)

{

Val=KeyPort&0xf0;

Val+=0x0e;

while(KeyPort!

=0xfe);

DelayMs(10);//去抖

while(KeyPort!

=0xfe);

returnVal;

}

KeyPort=0xfd;//检测第二行

if(KeyPort!

=0xfd)

{

Val=KeyPort&0xf0;

Val+=0x0d;

while(KeyPort!

=0xfd);

DelayMs(10);//去抖

while(KeyPort!

=0xfd);

returnVal;

}

KeyPort=0xfb;//检测第三行

if(KeyPort!

=0xfb)

{

Val=KeyPort&0xf0;

Val+=0x0b;

//松手检测

while(KeyPort!

=0xfb);

DelayMs(10);//去抖

while(KeyPort!

=0xfb);

returnVal;

}

KeyPort=0xf7;//检测第四行

if(KeyPort!

=0xf7)

{

Val=KeyPort&0xf0;

Val+=0x07;

while(KeyPort!

=0xf7);

DelayMs(10);//去抖

while(KeyPort!

=0xf7);

returnVal;

}

}

}

return0xff;

}

步进电机1相励磁驱动

//A相通电,其他相断电

#defineoil_A1{A1=1;B1=0;C1=0;D1=0;}

//B相通电,其他相断电

#defineCoil_B1{A1=0;B1=1;C1=0;D1=0;}

//C相通电,其他相断电

#defineCoil_C1{A1=0;B1=0;C1=1;D1=0;}

//D相通电,其他相断电

#defineCoil_D1{A1=0;B1=0;C1=0;D1=1;}

//全部断电

#defineCoil_OFF{A1=0;B1=0;C1=0;D1=0;}

while

(1)

{

Coil_A1

//改变以下参数可以调整电机转速,数字越小,转速越大,力矩越小

DelayMs(Speed);

Coil_B1

DelayMs(Speed);

Coil_C1

DelayMs(Speed);

Coil_D1

DelayMs(Speed);

}

}

 

步进电机1-2相励磁驱动

if(times==Speed)

{

times=0;

switch(i)

{

case0:

Coil_A1;i++;break;

case1:

Coil_AB1;i++;break;

case2:

Coil_B1;i++;break;

case3:

Coil_BC1;i++;break;

case4:

Coil_C1;i++;break;

case5:

Coil_CD1;i++;break;

case6:

Coil_D1;i++;break;

case7:

Coil_DA1;i++;break;

case8:

i=0;break;

default:

break;

}

}

elsetimes++;

电机按键控制

sbitDCOUT1=P1^1;//电机信号输出端口1

switch(num)

{

//电机1改变运行状态,数码管显示运行状态

case1:

DCOUT1=!

DCOUT1;

TempData[0]=0x5E;//'d'

TempData[1]=0x39;//'C'

TempData[2]=0x06;//'1'

if(DCOUT1)

{

TempData[5]=0x3F;//'O'

TempData[6]=0x54;//'n'

TempData[7]=0;

}

else

{

TempData[5]=0x3F;//'O'

TempData[6]=0x71;//'F'

TempData[7]=0x71;//'F'

}

break;

}

LCD1602*

//判断液晶忙,如果忙则等待

voidRead_Busy()

{

ucharbusy;

P0=0xff;

RS=0;

RW=1;

do

{

EN=1;

busy=P0;

EN=0;

}while(busy&0x80);

}

//写LCD1602命令一个字节

voidWrite_Cmd(ucharcmd)

{

Read_Busy();//判断忙

RS=0;

RW=0;

P0=cmd;

EN=1;

EN=0;

}

//写一个字节数据

voidWrite_Dat(uchardat)

{

Read_Busy();

RS=1;

RW=0;

P0=dat;

EN=1;

EN=0;

}

LCD1602

/*------------------------------------------------

判忙函数

------------------------------------------------*/

bitLCD_Check_Busy(void)

{

DataPort=0xFF;

RS_CLR;

RW_SET;

EN_CLR;

_nop_();

EN_SET;

return(bit)(DataPort&0x80);

}

/*------------------------------------------------

写入命令函数

------------------------------------------------*/

voidLCD_Write_Com(unsignedcharcom)

{

while(LCD_Check_Busy());//忙则等待

DelayMs(5);

RS_CLR;

RW_CLR;

EN_SET;

DataPort=com;

_nop_();

EN_CLR;

}

/*------------------------------------------------

写入数据函数

------------------------------------------------*/

voidLCD_Write_Data(unsignedcharData)

{

while(LCD_Check_Busy());//忙则等待

DelayMs(5);

RS_SET;

RW_CLR;

EN_SET;

DataPort=Data;

_nop_();

EN_CLR;

}

/*------------------------------------------------

写入字符串函数

------------------------------------------------*/

voidLCD_Write_String(ucharx,uchary,uchar*s)

{

if(y==0)LCD_Write_Com(0x80+x);

elseCD_Write_Com(0xC0+x);

while(*s)

{

LCD_Write_Data(*s);

s++;

}

}

/*------------------------------------------------

写入字符函数

------------------------------------------------*/

voidLCD_Write_Char(ucharx,uchary,ucharData)

{

if(y==0)LCD_Write_Com(0x80+x);

elseLCD_Write_Com(0xC0+x);

LCD_Write_Data(Data);

}

LCD1602键盘输入显示

while

(1)

{

num=KeyPro();

if(num!

=0xff)

{

if((i==0)&&(j==0))/回到第一个字符时清屏

LCD_Clear();//清屏

//依次显示输入字符

LCD_Write_Char(0+i,0+j,dofly_code[num]);

i++;

if(i==16)/如果第一行显示满,转到第二行

{

i=0;j++;

//如果2行都显示满,清屏后重新从第一行

显示

if(j==2)j=0;

}

}}

LCD1602动态显示

while

(1)

{

i=1;

p="";

LCD_Clear();

LCD_Write_String(2,0,"Welcometo");

DelayMs(250);

while(*p)

{

LCD_Write_Char(i,1,*p);

i++;

p++;

DelayMs(250);

}

DelayMs(250);

}

LCD602滚动显示

voidmain(void)

{

LCD_Init();

LCD_Clear();//清屏

LCD_Write_Char(7,0,'o');

LCD_Write_Char(8,0,'k');

LCD_Write_String(1,1,"");

while

(1)

{

DelayMs(200);

LCD_Write_Com(0x18);//左平移画面

/0x1C是右平移

}

}

 

LCD1602平移显示

while

(1)

{

pa="Welcometo";

pb="";

LCD_Clear();

LCD_Write_String(2,0,pa);//显示2行信息

LCD_Write_String(1,1,pb);

for(i=0;i<8;i++)DelayMs(250);/延时2s左右

LCD_Clear();//清屏显示其他信息

i=2;

while(*pa)//循环输入方式显示2行信息

{

LCD_Write_Char(i,0,*pa);

i++;

pa++;

DelayMs(250);

}

i=1;

while(*pb)

{

LCD_Write_Char(i,1,*pb);

i++;

pb++;

DelayMs(250);

}

DelayMs(250);

}

 

LCD1602

//*******************显示一个字节数据

voidDisplayOneChar(ucharX,ucharY,ucharDData)

{

//Y=1显示第二行,Y=0显示第一行

if(Y)X|=0X40;

X|=0X80;

Lcd1602_Write_Cmd(X);/X用来选择哪位

Lcd1602_Write_Data(DData);//DData用来

写数据

}

//显示一个字节字符

voidDisplayOneStr(ucharX,ucharY,ucharDData)

{

DisplayOneChar(X++,Y,DData/16+'0');

DisplayOneChar(X,Y,DData%16+'0');

}

//显示字符串

voidLcdShowStr(ucharx,uchary,uchar*str)

{

LcdSetCursor(x,y);//当前字符的坐标

while(*str!

=\0')Lcd1602_Write_Data(*str++);

}

voidInitLcd1602()//1602初始化

{

//打开5*8,8位数据

Lcd1602_Write_Cmd(0x38);

Lcd1602_Write_Cmd(0x0c);

Lcd1602_Write_Cmd(0x06);

Lcd1602_Write_Cmd(0x01);//清屏

}

 

DS1302突发模式些时钟

while

(1)

{

Read_DS1302_Time();//时钟突发模式读

DisplayOneStr(5,0,TimeData[6]);//年

DisplayOneChar(7,0,'-');//-

DisplayOneStr(8,0,TimeData[4]);//月

DisplayOneChar(10,0,'-');//-

DisplayOneStr(11,0,TimeData[3]);//日

DisplayOneChar(13,0,'-');//-

DisplayOneStr(14,0,TimeData[5]);//星期

DisplayOneStr(6,1,TimeData[2]);//时

DisplayOneChar(8,1,':

');//:

DisplayOneStr(9,1,TimeData[1]);//分

DisplayOneChar(11,1,':

');//:

DisplayOneStr(12,1,TimeData[0]);//秒

Delay_Ms(1000);//延时1秒

}

8*8点阵左移显示

while

(1)

{

for(j=0;j<16;j++)

{

for(i=0;i<50;i++)

{

temp=0x7f;

for(k=0;k<16;k++)//一个字母BYTE

{

Send_Byte(temp);//列选择

Send_Byte(Display_word[j+k]);//数据

LEDARRAY_LAT=1;//锁存数据

_nop_();

LEDARRAY_LAT=0;

_nop_();

Temp=(temp>>1)|0x80;

}}}}

红外接受1

voidint0()interrupt0//定义外部中断0

{

staticuchari;

staticbitstartflag;//开始储存脉宽标志位

if(startflag)//开始接收脉宽检测

{

/*判断是否是引导码,底电平9000us+高4500us,这个自己可以算我以11.0592来算了NEC协议的引导码低8000-10000+高4000-5000如果已经接收了引导码那么i不会被置0就会开始依次存入脉宽*/

//如果是引导码那么执行i=0把他存到

//IRdata的第一个位

if((IRtime<53)&&(IRtime>=32))i=0;

/

IRdata[i]=IRtime;//以T0的溢出次数来//计算脉宽,把这个时间//存到数组里面到后面判断

IRtime=0;//计数清零,下一个下降沿的时//候在存入脉宽

i++;//计数脉宽存入的次数

if(i==33)

{

IRok=1;//那么表示脉宽检测完毕

i=0;//把脉宽计数清零准备下次存入

}

}

else

{

IRtime=0;//引导码开始进入把脉宽计数//清零开始计数

s

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 >

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1