单片机程序知识点剖析.docx
- 文档编号:13135134
- 上传时间:2023-06-11
- 格式:DOCX
- 页数:27
- 大小:131.40KB
单片机程序知识点剖析.docx
《单片机程序知识点剖析.docx》由会员分享,可在线阅读,更多相关《单片机程序知识点剖析.docx(27页珍藏版)》请在冰点文库上搜索。
单片机程序知识点剖析
单片机程序知识点
按键扫描支持连续按一般思路
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;//引导码开始进入把脉宽计数//清零开始计数
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 程序 知识点 剖析