单片机设计与开发 课件 程艳辉 第2章 模块程序设计_第1页
单片机设计与开发 课件 程艳辉 第2章 模块程序设计_第2页
单片机设计与开发 课件 程艳辉 第2章 模块程序设计_第3页
单片机设计与开发 课件 程艳辉 第2章 模块程序设计_第4页
单片机设计与开发 课件 程艳辉 第2章 模块程序设计_第5页
已阅读5页,还剩219页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第2章模块程序设计前页

返回2.1LED

☆2.2定时器

☆2.3数码管

☆2.4矩阵按键

☆2.5中断

☆2.6串行口

☆2.7实时时钟DS1302

☆2.8温度传感器DS18B20

☆2.9串行EEPROMAT24C02

☆2.108位ADC/DACPCF8591

☆2.11超声波距离测量

☆2.12频率测量

☆2025/11/17单片机设计与开发第2章模块程序设计前页

返回2.1LED系统包括MCU(IAP15F2K61S2)译码器(74HC138和74HC02)锁存器(74HC573)和LED(L1~L8)等。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.1LEDLED(L1~L8)采用共阳极连接,低电平点亮,高电平熄灭(负逻辑)。锁存器对单片机P0口的输出信号进行锁存,并增强信号驱动能力进而驱动LED发光。锁存器的锁存输入Y4C是译码器输入P27~P25为100时的有效输出17:35:20单片机设计与开发第2章模块程序设计前页

返回2.1LED设计任务:用LED实现4个亮度等级显示。设计思路:通过改变LED的亮灭时间实现不同亮度等级的显示。2.1.1程序设计2.1.2程序调试17:35:20单片机设计与开发第2章模块程序设计前页

返回2.1LED2.1.1程序设计基于单片机竞赛实训平台的LED亮度控制程序设计如下://使用程序前,将J13调整为IO模式(2-3脚短接)sfrP0=0x80;sfrP2=0xA0;//P0输出:ucData——数据,ucAddr——地址(4~7)voidP0_Out(unsignedcharucData,unsignedcharucAddr){P0=ucData; //P0输出数据P2|=ucAddr<<5; //置位P27~P25P2&=0x1f; //复位P27~P25//XBYTE[ucAddr<<13]=ucData; //MM模式(J13-2和J13-1相连)}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.1LED2.1.1程序设计基于单片机竞赛实训平台的LED亮度控制程序设计如下://关闭外设voidClose_Peripheral(void){P2&=0x1f;//复位P27~P25P0_Out(0xff,LED);//熄灭LEDP0_Out(~(RLY|BUZ),ULN);//关闭继电器和蜂鸣器}//LED显示voidLed_Disp(unsignedcharucLed){P0_Out(~ucLed,4);//LED显示}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.1LED2.1.1程序设计基于单片机竞赛实训平台的LED亮度控制程序设计如下://延时函数(最小约1ms@12MHz)voidDelay(unsignedintuiNum){unsignedinti;while(uiNum--)for(i=0;i<628;i++);}//主函数voidmain(void){unsignedchari,j;Close_Peripheral();17:35:20单片机设计与开发第2章模块程序设计前页

返回2.1LED2.1.1程序设计基于单片机竞赛实训平台的LED亮度控制程序设计如下:while(1){for(i=0;i<4;i++) //4个亮度等级for(j=0;j<64;j++){Led_Disp(0xff); //L1~L8点亮Delay(i+1); //延时时间依次是1ms、2ms、3ms和4msLed_Disp(0); //L1~L8熄灭Delay(4-i); //延时时间依次是4ms、3ms、2ms和1ms}}}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.1LED2.1.2程序调试LED程序调试包括关闭外设调试和LED显示调试两部分。①

单击“Project”菜单下的“BuildTarget”菜单项或单击生成工具栏中的“Build”按钮编译工程。②

编译正确后,单击“Debug”菜单下的“Start/StopDebugSession”菜单项或单击文件工具栏中“Start/StopDebugSession”按钮进入调试界面。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.1LED2.1.2程序调试LED程序调试包括关闭外设调试和LED显示调试两部分。③

单击“Peripherals”菜单下“I/O-Ports”中的“Port0”和“Port2”,打开“ParallerPort0”和“ParallerPort2”对话框,如图2.3所示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.1LED2.1.2程序调试LED程序调试包括关闭外设调试和LED显示调试两部分。(1)关闭外设调试(2)LED显示调试17:35:20单片机设计与开发第2章模块程序设计前页

返回2.1LED2.1.2程序调试思考:LED显示时ucLed为什么要进行位非(~)操作?可以换成逻辑非(!)吗?扩展:将亮度等级修改为16级。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器IAP15F2K61S2单片机内部集成了3个16位的定时器/计数器T0、T1和T2,其核心部件是一个加法计数器(TH和TL),可以对输入脉冲进行计数。若计数脉冲来自系统时钟,则为定时器方式;若计数脉冲来自T0(P34)、T1(P35)或T2(P31)引脚,则为计数方式。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器与3个定时器相关的特殊功能寄存器如表2.1所示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器与3个定时器相关的特殊功能寄存器如表2.1所示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器定时器/计数器T0和T1具有四种工作方式,由特殊功能寄存器TMOD中的M1和M0位决定,如表2.2所示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器16位定时初值(高8位在TH中,低8位在TL中)与定时时间的关系是:12T方式定时初值=65536-定时时间*系统主频/121T方式定时初值=65536-定时时间*系统主频定时初值/256商放入TH余数放入TL17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器STC-ISP是一款官方程序下载与辅助开发软件。它通过串口利用ISP功能将程序烧录到芯片中,从而实现设备功能的更新。其内置的定时器计算器、波特率计算器等工具,能根据用户设置自动生成C或ASM代码片段,提升开发效率。基于单片机竞赛实训平台,设置系统频率为12.000MHz,设置定时时长为1ms,选择定时器1,选择定时器模式为16位自动重载,选择定时器时钟为12T(FOSC/12),即可生成相应的C代码,如图2.6所示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器设计任务:用LED实现16个亮度等级显示。设计思路:亮度等级用10位uiTms(周期1s)的高4位(uiTms>>6)实现,每个亮度等级显示64ms,为了避免闪烁,将64ms分为4个16ms,16个亮度等级的16ms数为64(uiTms&0x3f0)。2.2.1程序设计2.2.2程序实现2.2.3程序调试17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.1程序设计定时器程序设计在LED程序设计的基础上完成:在“D:\CT107D_2506”文件夹中将“201_LED”文件夹复制粘帖并重命名为“202_TIM”文件夹,打开“202_TIM”文件夹中的“IAP15”工程。定时器程序设计包括tim.h设计和tim.c设计。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.1程序设计(1)tim.h设计定时器头文件“tim.h”内容如下(存放在“D:\CT107D_2506\202_TIM”文件夹中):#ifndef__TIM_H#define__TIM_HvoidT1_Init(void);voidT1_Proc(void);#endif17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.1程序设计(2)tim.c设计定时器头文件“tim.c”内容如下(存放在“D:\CT107D_2506\202_TIM”文件夹中):sfrTCON=0x88;sfrTMOD=0x89;sfrAUXR=0x8E;sfrTL1=0x8B;sfrTH1=0x8D;sbitTR1=TCON^6;sbitTF1=TCON^7;17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.1程序设计(2)tim.c设计voidT1_Init(void) //1毫秒@12.000MHz{AUXR&=0xBF; //定时器时钟12T模式TMOD&=0x0F; //设置定时器模式TL1=0x18; //设置定时初值(24)TH1=0xFC; //设置定时初值(252)TF1=0; //清除TF1标志TR1=1; //定时器1开始计时}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.1程序设计(2)tim.c设计externunsignedintuiTms; //毫秒值externunsignedintuiSec; //秒值externunsignedintuiDuty; //亮度等级(占空比)voidT1_Proc(void){if(!TF1) //1ms时间未到return;TF1=0; //清除TF1标志17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.1程序设计(2)tim.c设计if(++uiTms==1000) //1s时间到{uiTms=0;uiSec++;}

uiDuty=(uiTms&0x3f0)+(uiTms>>6);}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.2

程序实现定时器程序实现的方法是:(1)在“202_TIM”文件夹中新建文件“tim.h”和“tim.c”。(2)将文件“tim.c”添加到“SourceGroup1”中。(3)在“main.c”中做如下修改:①

包含下列头文件:#include"tim.h"②

添加下列全局变量声明:unsignedintuiTms; //毫秒值unsignedintuiSec; //秒值unsignedintuiDuty; //亮度等级(占空比)17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.2

程序实现定时器程序实现的方法是:③

添加下列函数声明:voidLed_Proc(void);④

删除Delay()函数以及i和j的声明。⑤

在main()的初始化部分添加下列语句:T1_Init();⑥

将while(1)循环体替换为下列语句:T1_Proc();Led_Proc();17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.2

程序实现⑦

在main()函数后添加下列函数:voidLed_Proc(void){if(uiTms<uiDuty)Led_Disp(0xff);elseLed_Disp(0);}生成目标程序,进入调试界面下载并运行程序,L1~L8以16个亮度等级循环显示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.3

程序调试定时器程序调试包括T1初始化调试、T1处理调试和LED处理调试3部分。①

单击“Project”菜单下的“BuildTarget”菜单项或单击生成工具栏中的“Build”按钮编译工程,②

编译正确后,单击“Debug”菜单下的“Start/StopDebugSession”菜单项或单击文件工具栏中“Start/StopDebugSession”按钮进入调试界面。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.3

程序调试定时器程序调试包括T1初始化调试、T1处理调试和LED处理调试3部分。③

单击“Debug”菜单下的“AllTimers”菜单项,打开Timer对话框,如图2.7所示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.3

程序调试定时器程序调试包括T1初始化调试、T1处理调试和LED处理调试3部分。(1)T1初始化调试(2)T1处理调试(3)LED处理调试17:35:20单片机设计与开发第2章模块程序设计前页

返回2.2定时器2.2.3

程序调试思考:①与T1相关的寄存器位有哪些?含义各是什么?②T1的16位定时初值(TH和TL的值)如何确定?扩展:用T0或T2实现1s定时功能(T0或T2定时10ms)。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管数码管是一种半导体发光器件,其基本单元是发光二极管。数码管按段数分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元(小数点显示);按能显示多少个“8”可分为1位、2位和4位等;按发光二极管单元连接方式分为共阳极数码管和共阴极数码管。共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极COM接到电源,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极COM接到地,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管数码管要正常显示,就要用驱动电路驱动数码管的各个段码,从而显示出需要显示的数字。根据数码管驱动方式的不同,可以分为静态式和动态式两类。①静态显示驱动:静态驱动也称直流驱动,静态驱动是指每个数码管的每一个段码都由一个单片机的I/O端口进行驱动,或者使用如BCD码或二-十进制译码器进行驱动。静态驱动的优点是编程简单,显示亮度高,缺点是占用I/O端口多,如驱动4个数码管静态显示则需要4×8=32根I/O端口来驱动,而MCS51单片机可用的I/O端口才32个。实际应用时必须增加译码驱动器进行驱动,增加了硬件电路的复杂性。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管数码管要正常显示,就要用驱动电路驱动数码管的各个段码,从而显示出需要显示的数字。根据数码管驱动方式的不同,可以分为静态式和动态式两类。②动态显示驱动:数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划“a、b、c、d、e、f、g和dp”的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制。当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是哪个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的COM端,就使各个数码管轮流受控显示,这就是动态驱动。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管数码管要正常显示,就要用驱动电路驱动数码管的各个段码,从而显示出需要显示的数字。根据数码管驱动方式的不同,可以分为静态式和动态式两类。②动态显示驱动:数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划“a、b、c、d、e、f、g和dp”的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制。在轮流显示过程中,每位数码管的点亮时间为1-2ms,由于人眼的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感。动态显示的效果和静态显示是一样的,但能够节省大量的I/O端口,而且功耗更低。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管系统包括MCU(IAP15F2K61S2)译码器(74HC138和74HC02)锁存器(74HC573)LED(L1~L8)和数码管(DS1~DS2)等。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管数码管(DS1~DS2)采用2个锁存器对单片机P0口的输出信号进行锁存,并增强信号驱动能力进而驱动8个数码管。U8是位选,锁存器的锁存输入Y6C是译码器输入P27~P25为110时的有效输出。U7是段选,锁存器的锁存输入Y7C是译码器输入P27~P25为111时的有效输出。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管设计任务:用T1实现秒计时,用LED和数码管显示秒值。2.3.1程序设计2.3.2程序实现2.3.3程序调试17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.1程序设计数码管设计在LED流水灯(定时器延时1s)设计的基础上完成:在“D:\CT107D_2506”文件夹中将“202_TIM”文件夹复制粘贴为“203_SEG”文件夹,打开“203_SEG”文件夹中的“IAP15”工程。数码管程序设计包括seg.h设计、seg.c设计和tim.c修改。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.1程序设计(1)seg.h设计数码管头文件“seg.h”内容如下:voidClose_Peripheral(void);voidLed_Disp(unsignedcharucLed);voidUln_Ctrl(unsignedcharucUln);voidSeg_Tran(unsignedchar*pucSeg_Buf,unsignedchar*pucSeg_Code);voidSeg_Disp(unsignedcharucSeg_Code,unsignedcharucSeg_Pos);17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.1程序设计(2)seg.c设计数码管源文件“seg.c”内容如下:sfrP0=0x80;sfrP2=0xA0;//P0输出:ucData——数据,ucAddr——地址(4~7)voidP0_Out(unsignedcharucData,unsignedcharucAddr){P0=ucData;//P0输出数据P2|=ucAddr<<5;//置位P27~P25P2&=0x1f;//复位P27~P25}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.1程序设计(2)seg.c设计//LED显示:ucLed——LED值voidLed_Disp(unsignedcharucLed){P0_Out(~ucLed,4);}//ULN控制:ucUln=0:关闭继电器,ucUln=0x10:打开继电器voidUln_Ctrl(unsignedcharucUln){P0_Out(ucUln,5);}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.1程序设计(2)seg.c设计//关闭外设voidClose_Peripheral(void){P2&=0x1f;//复位P27~P25Led_Disp(0);//熄灭LEDUln_Ctrl(0);//关闭继电器和蜂鸣器}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.1程序设计(2)seg.c设计//数码管转换:pucSeg_Char——显示字符,pucSeg_Code——显示代码voidSeg_Tran(unsignedchar*pucSeg_Buf,unsignedchar*pucSeg_Code){unsignedchari,j=0,temp;17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.1程序设计(2)seg.c设计for(i=0;i<8;i++,j++){switch(pucSeg_Buf[j]){//低电平点亮段,段码[MSB...LSB]对应码顺序为[dpgfedcba]case'0':temp=0xc0;break; //11000000case'1':temp=0xf9;break;//11111001//case'1':temp=0xcf;break;//11001111

…………………………default:temp=0xff;//11111111}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.1程序设计(2)seg.c设计if(pucSeg_Buf[j+1]=='.'){temp=temp&0x7f; //点亮小数点j++;}pucSeg_Code[i]=temp;}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.1程序设计(2)seg.c设计//数码管显示:pucSeg_Code-显示代码,ucSeg_Pos-显示位置voidSeg_Disp(unsignedchar*pucSeg_Code,unsignedcharucSeg_Pos){P0_Out(0xFF,SEG);//消隐P0_Out(1<<ucSeg_Pos,POS);//位选P0_Out(pucSeg_Code[ucSeg_Pos],SEG);//段选}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.1程序设计(3)tim.c修改在“tim.c”中做如下修改:①添加下列外部变量声明:externunsignedintuiSeg_Dly;//显示刷新延时externunsignedcharucSeg_Dly;//显示移位延时②在T1_Proc()的后部添加下列语句:uiSeg_Dly++;ucSeg_Dly++;17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.2程序实现数码管程序实现的方法是:(1)在“Driver”文件夹中新建文件“seg.h”和“seg.c”,修改“tim.c”。(2)将文件“seg.c”添加到“SourceGroup1”中。(3)在“main.c”中做如下修改:①

包含下列头文件:#include"seg.h"#include<stdio.h>②

删除P0_Out()、Close_Peripheral()和Led_Disp()函数体。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.2程序实现③

添加下列函数声明:voidSeg_Proc(void);④

在while(1)循环体中添加下列语句:Seg_Proc();⑤

在main()和Led_Proc()函数中间添加下列代码:unsignedcharpucSeg_Char[12]; //显示字符unsignedcharpucSeg_Code[8]; //显示代码unsignedcharucSeg_Pos; //显示位置unsignedintuiSeg_Dly; //显示刷新延时unsignedcharucSeg_Dly; //显示移位延时17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.2程序实现voidSeg_Proc(void){if(uiSeg_Dly>=300) //300ms刷新1次{uiSeg_Dly=0;sprintf(pucSeg_Char,"1.%04u",uiSec);Seg_Tran(pucSeg_Char,pucSeg_Code);}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.2程序实现//可以用中断方式实现数码管循环显示(参见3.2.1、3.4.1和3.5.1)if(ucSeg_Dly>=2) //2ms移位1次{ucSeg_Dly=0;Seg_Disp(pucSeg_Code[ucSeg_Pos],ucSeg_Pos);ucSeg_Pos=++ucSeg_Pos&7; //数码管循环显示}}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.2程序实现⑥

将Led_Proc()的函数体替换为下列代码:Led_Disp(uiSec);(4)把“..\Driver”添加到包含路径中。生成目标程序,进入调试界面下载并运行程序,数码管上显示变化的秒值。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.3程序调试数码管程序调试包括数码管转换调试和数码管显示调试。(1)数码管转换调试17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.3程序调试数码管程序调试包括数码管转换调试和数码管显示调试。(1)数码管转换调试(2)数码管显示调试17:35:20单片机设计与开发第2章模块程序设计前页

返回2.3数码管2.3.3程序调试思考:①数码管动态显示主要包括哪几个步骤?②uiSeg_Dly和ucSeg_Dly的作用有何区别?③数码管字形码如何确定?添加“_”的字形码。扩展:将数码管旋转180°显示(可以显示℃)。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键矩阵键盘是单片机外部设备中所使用的排布类似于矩阵的键盘组。在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。在矩阵键盘中,在每条水平线和垂直线交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P0口)就可以构成4*4=16个按键,比直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,列线通过电阻接正电源,并将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。这样,当按键没有按下时,所有的输入端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键矩阵键盘中按键的识别有行/列扫描和线翻转两种方法,其中行/列扫描法是一种最常用的按键识别方法,过程如下:①逐行输出0,检查列线是否非全高;②如果某行输出0时,查到列线非全高,则该行有按键按下;③根据输出0的行线和读入0的列线,即可判断按下按键的位置。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键设计任务:用按键按下、松开、双击和长按切换系统状态,用LED和数码管显示状态。2.4.1程序设计2.4.2程序实现2.4.3程序调试17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.1程序设计矩阵按键的原理框图和原理图与数码管相同,矩阵按键程序设计在数码管程序设计的基础上完成:在“D:\CT107D_2506”文件夹中将“203_SEG”文件夹复制粘贴为“204_KEY”文件夹,打开“204_KEY”文件夹中的“IAP15”工程。矩阵按键程序设计包括key.h设计、key.c设计和tim.c修改。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.1程序设计(1)key.h设计矩阵键盘头文件“key.h”内容如下:#ifndef__KEY_H#define__KEY_HunsignedcharKey_Read(void);#endif17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.1程序设计(2)key.c设计矩阵键盘源文件“key.c”内容如下://运行程序时,将J5调整为KBD模式(1-2脚短接)sfrP3=0xB0;sfrP4=0xC0;sbitP34=P3^4;sbitP35=P3^5;sbitP42=P4^2;sbitP44=P4^4;17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.1程序设计(2)key.c设计//读取按键值:返回值-按键值unsignedcharKey_Read(void){unsignedintuiKey_Code;P44=0;P42=1;P35=1;P34=1; //第1列(S4~S7)uiKey_Code=P3;P44=1;P42=0; //第2列(S8~S11)uiKey_Code=(uiKey_Code<<4)|(P3&0x0f);P42=1;P35=0; //第3列(S12~S15)uiKey_Code=(uiKey_Code<<4)|(P3&0x0f);P35=1;P34=0; //第4列(S16~S19)uiKey_Code=(uiKey_Code<<4)|(P3&0x0f);17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.1程序设计(2)key.c设计switch(~uiKey_Code){case0x8000:return4; //S4case0x4000:return5; //S5case0x2000:return6; //S6case0x1000:return7; //S7

………………case0x0001:return19; //S19case0x0c00:return20; //S8+S9default:return0;}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.1程序设计(2)key.c设计//独立按键程序代码,将J5调整为BTN模式(2-3脚短接)/*switch(~P3&0xf){case0x8:return4; //S4case0x4:return5; //S5case0x2:return6; //S6case0x1:return7; //S7default:return0;}*/17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.1程序设计(3)tim.c修改①添加下列外部变量声明:externunsignedcharucKey_Dly; //按键刷新延时externunsignedintuiKey_Dly; //双击或长按延时②在T1_Proc()的后部添加下列语句:ucKey_Dly++;uiKey_Dly++;17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.2程序实现矩阵键盘程序实现的方法是:(1)在“Driver”文件夹中新建文件“key.h”和“key.c”,修改“tim.c”。(2)将文件“key.c”添加到“SourceGroup1”中。(3)在“main.c”中做如下修改:①

包含下列头文件:#include"key.h"②

添加下列全局变量声明:unsignedcharucState; //系统状态17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.2程序实现矩阵键盘程序实现的方法是:③

添加下列函数声明:voidKey_Proc(void);④

在while(1)循环体中添加下列语句:Key_Proc();⑤

在Seg_Proc()中将下列语句:sprintf(pucSeg_Char,"1.%04u",uiSec);替换为:sprintf(pucSeg_Char,"%02x%04u",(int)ucState,uiSec);17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.2程序实现⑥

在Seg_Proc()和Led_Proc()函数之间添加下列代码:unsignedcharucKey_Old; //旧键值unsignedcharucKey_Dly; //按键刷新延时unsignedintuiKey_Dly=500; //双击或长按延时voidKey_Proc(void){unsignedcharucKey_Dn,ucKey_Up;if(ucKey_Dly<10) //延时10ms消抖return;ucKey_Dly=0;17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.2程序实现ucKey_Dn=Key_Read(); //键值读取if(ucKey_Dn!=ucKey_Old) //键值变化{ucKey_Up=ucKey_Old; //保存键值ucKey_Old=ucKey_Dn;}else{ucKey_Up=0; //清除键值ucKey_Dn=0;}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.2程序实现if(ucKey_Dn==4) //S4按键按下{ucState^=0x10; //修改主状态(L5翻转)if(uiKey_Dly<500) //S4按键双击ucState^=2; //修改次状态(L2翻转)uiKey_Dly=0; //开始计时}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.2程序实现if(ucKey_Up==4) //S4按键松开ucState^=1; //修改次状态(L1翻转)if((ucKey_Old==4)&&(uiKey_Dly>1000)){ //S4按键长按ucState^=4; //修改次状态(L3翻转)uiKey_Dly=0; //重新计时}}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.2程序实现⑦

将Led_Proc()的函数体替换为下列代码:Led_Disp(ucState);生成目标程序,进入调试界面下载并运行程序,数码管上显示系统状态(前2位)和变化的秒值(后4位),L1~L8熄灭。按下S4按键,状态显示10,L5点亮,松开S4按键,状态显示11,L1点亮。按下S4按键,状态显示01,L5熄灭,松开S4按键,状态显示00,L1熄灭。500ms内2次按下S4按键,状态显示02,L2点亮;再2次按下S4按键,状态显示00,L2熄灭。长按S4按键超过1s,状态显示15,L1、L3和L5点亮;再长按S4按键超过1s,状态显示00,L1、L3和L5熄灭。17:35:20单片机设计与开发2.4矩阵按键2.4.3程序调试矩阵按键程序调试包括键值读取调试和键值处理调试。(1)键值读取调试(2)键值处理调试第2章模块程序设计前页

返回17:35:20单片机设计与开发2.4矩阵按键2.4.3程序调试(2)键值处理调试可以看出:键值处理程序将3个有效按键状态(按键按下、按键按住和按键松开,由ucKey_Dn和ucKey_Old的3种组合表示),转换成3个独立的状态(分别由ucKey_Dn、ucKey_Up和ucKey_Old表示)第2章模块程序设计前页

返回17:35:20单片机设计与开发2.4矩阵按键2.4.3程序调试注意:由于在线调试也使用P30(TXD)和P31(RXD),所以按下第1行和第2行按键时会退出在线调试。注意:由于频率测量也使用P34,所以频率测量时第4列按键不能正常工作。为了使第4列按键能够正常工作,需要拔掉J3_15(SIG)和J3_16(P34)上的短路块。第2章模块程序设计前页

返回17:35:20单片机设计与开发第2章模块程序设计前页

返回2.4矩阵按键2.4.3程序调试思考:①矩阵按键行扫描法判断按键动作主要包括哪几个步骤?②ucKey_Dly和uiKey_Dly的作用是什么?③矩阵按键的扫描码如何确定?扩展:①

用线翻转法实现按键识别。②

用独立按键实现按键操作。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断中断是重要的接口数据传送控制方式,可以使CPU具有实时处理事件的能力,当事件发生时,CPU暂停正在执行的程序转去对事件进行处理,处理完成后再返回原来的程序继续执行。发生的事件称为中断源,中断源产生中断请求,在中断允许的情况下CPU响应中断,执行中断处理程序。中断处理程序与子程序有相似之处,但也有下列本质区别:●什么时候调用子程序是确定的,而什么时候产生中断是不确定的。●子程序的起始地址由调用程序给出,而MCS51中断程序的起始地址是固定的。●子程序的执行一般是无条件的,而中断处理程序的执行要先使能中断。为了区分不同的重要程度,中断具有优先级,高优先级的中断可以中断低优先级的中断处理,但任何中断不能中断相同优先级的中断处理。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断IAP15F2K61S2系列单片机提供了14个中断请求源,它们分别是:外部中断0(INT0)、定时器0中断、外部中断1(INT1)、定时器1中断串行口1中断、ADC中断、低压检测(LVD)中断、CCP/PWM/PCA中断串行口2中断、SPI中断、外部中断2(INT2)、外部中断3(INT3)定时器2中断以及外部中断4(INT4)除外部中断2(INT2)、外部中断3(INT3)、定时器2中断和外部中断4(INT4)固定是最低优先级中断外,其它的中断都具有2个中断优先级,可实现2级中断服务程序嵌套。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断中断源信息如表2.4所示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断中断源信息如表2.4所示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断与中断相关的特殊功能寄存器(SFR)如表2.5所示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断中断允许位为0时禁止相应中断,为1时允许相应中断。EA为0时禁止所有中断,为1时允许所有中断。中断优先级位为0时是低优先级中断,为1时是高优先级中断。对于外部中断INT0和INT1,TCON中的IT0和IT1决定触发中断的条件,为0时上升沿和下降沿都可触发中断,为1是只有下降沿可以触发中断。INT0和INT1的中断请求标志分别是IE0和IE1,中断产生时由硬件置位,响应中断后由硬件复位。外部中断INT2~INT4都只能下降沿触发中断,中断请求标志用户不可见,中断优先级固定为0(低优先级)。定时器中断T0和T1的中断请求标志分别是TF0和TF1,中断产生时由硬件置位,响应中断后由硬件复位。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断串行口的发送和接收公用一个中断,中断响应后必须在中断处理程序中通过查询中断请求标志判断是接收中断还是发送中断,然后分别进行处理,并用软件复位中断请求标志。中断处理函数的一般形式为:void函数名(void)interruptn[usingm]其中n是中断号(0~12,16),编译器从8n+3处产生中断入口地址。m用来选择工作寄存器组(0~3)。using是可选项,不选时编译器自动选择工作寄存器组。应该特别注意:在任何情况下都不能直接调用中断处理函数,因此它不能进行参数传递,也没有返回值。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断设计任务:用中断方式实现T1定时。2.5.1程序设计2.5.2程序调试17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断2.5.1程序设计T1中断程序设计在矩阵键盘程序设计的基础上完成:在“D:\CT107D_2506”文件夹中将“204_KEY”文件夹复制粘帖并重命名为“205_INT”文件夹,打开“205_INT”文件夹中的“IAP15”工程。T1中断程序设计包括T1中断允许和T1中断处理。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断2.5.1程序设计(1)T1中断允许T1中断允许设计如下:①

在tim.c中添加下列定义:sfrIE=0xA8;sbitET1=IE^3;sbitEA=IE^7;②

在T1_Init()的后部添加下列语句:ET1=1; //允许T1中断EA=1; //允许系统中断17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断2.5.1程序设计(2)T1中断处理①

在tim.c中修改下列函数:voidT1_Proc(void)interrupt3②

删除T1_Proc()中的下列语句:if(!TF1) //1ms时间未到return;TF1=0; //清除TF1标志③

删除while(1)中的下列语句:T1_Proc();17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断2.5.2程序调试定时器T1中断程序的调试步骤如下:①

编译工程,进入调试界面。②

在T1_Proc()中的下列语句处设置断点:if(++uiTms==1000) //1s时间到③

运行程序,程序停在断点处,中断系统工作正常。④

取消断点,退出调试界面。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.5中断2.5.2程序调试思考:①中断操作主要包括哪2个步骤?②对比中断和查询程序,找出两者的不同点和相同点。扩展:用中断方式实现串行口接收。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口数据传输有并行和串行两种方式,并行传输是多位(8位、16位或32位)一起传输,速度快但传输距离近,而串行传输是逐位传输,速度慢但传输距离远。两种方式分别通过并行接口和串行接口实现。串行接口又分为异步和同步两种方式,异步串行接口不要求有严格的时钟同步,常用的异步串行接口是UART(通用异步收发器),而同步串行接口要求有严格的时钟同步,常用的同步串行接口有SPI(串行设备接口)和I2C(内部集成电路接口)等。串行接口连接串行设备时必须遵循相关的物理接口标准,这些标准规定了接口的机械、电气、功能和过程特性。UART的物理接口标准有RS-232C、RS-449(其中电气标准是RS-422或RS-423)和RS-485等,其中RS-232C和RS-485是最常用的UART物理接口标准。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口RS-232C电气特性采用负逻辑:逻辑“1”的电平低于-3V,逻辑“0”的电平高于+3V,这和TTL的正逻辑(逻辑“1”为高电平,逻辑“0”为低电平)不同,因此通过RS-232C和TTL器件通信时必须进行电平转换。RS-232C采用单端输出和单端输入,最大通信距离约30m,通信速率低于20Kbps。RS-422和RS-485则采用平衡输出和差分输入,传输一个信号两根线,利用两根线的电压差表示逻辑“0”和“1”。由于采用双线传输,抗共模干扰能力增强,距离10m时速率可达10Mbps,距离1000m时速率仍可达100Kbps。RS-232C和RS-422都可以全双工工作(发送和接收可以同时进行),只能实现点对点通信。而RS-485采用半双工工作(发送和接收不能同时进行),最大可以连接32个节点,增加驱动后(例如SIT3485),最大可以连接256个节点。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口目前微控制器的UART接口采用的是TTL正逻辑,和TTL器件连接不需要电平转换。和采用负逻辑的计算机相连时需要进行电平转换,或使用UART-USB转换器连接。UART常用的引脚只有3个:TxD(发送数据)、RxD(接收数据)和GND(地),两个UART连接时,TxD和RxD必须交叉连接。UART的主要指标有2个:数据速率和数据格式。数据速率用波特率表示,数据格式包括1个起始位、5-8个数据位、0-1个校验位和1-2个停止位。通信双方的数据速率和数据格式必须一致,否则无法实现通信。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口IAP15F2K61S2单片机内部有2个采用UART工作方式的全双工串行通信接口(串行口1和串行口2)。每个串行口由2个数据缓冲器、1个移位寄存器、1个串行控制器和1个波特率发生器等组成。每个串行口的数据缓冲器由2个相互独立的接收、发送缓冲器构成,可以同时发送和接收数据。发送数据缓冲器只能写入而不能读出,接收缓冲器只能读出而不能写入,因而两个缓冲器可以公用一个地址码。串行口1的两个数据缓冲器的公用地址码是99H,串行口2的两个数据缓冲器的公用地址码是9BH。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口IAP15F2K61S2单片机与串行口相关的特殊功能寄存器如表2.6所示。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口UART1的4种工作方式如表2.7所示。UART1通常工作在方式1,可以用T1(方式0,AUXR中的S1_ST2为0)或T2(AUXR中的S1_ST2为1,复位值)作为波特率发生器。定时初值=65536-系统主频/波特率/48波特率=系统主频/(65536-定时初值)/4817:35:20单片机设计与开发2.6串行口常用波特率的定时初值如表2.8所示。从表中可以看出,系统主频为11.0592MHz时实际波特率没有误差,这也就是系统主频常用11.0592MHz的原因。系统主频为12MHz时由于实际波特率存在误差,可能无法与其他串行设备正常通信。第2章模块程序设计前页

返回17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口设计任务:用串行口发送和设置秒值。2.6.1程序设计2.6.2程序调试17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口2.6.1程序设计串行口程序设计在T1中断程序设计的基础上完成:在“D:\CT107D_2506”文件夹中将“205_INT”文件夹复制粘帖并重命名为“206_UART”文件夹,打开“206_UART”文件夹中的“IAP15”工程。串行口程序设计包括uart.h设计、uart.c设计、tim.c修改和main.c修改。17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口2.6.1程序设计(1)uart.h设计串行口头文件“uart.h”内容如下:#ifndef__UART_H#define__UART_HvoidUart_Init(void);voidUart_RecvString(void);voidUart_SendChar(unsignedchar*pucStr);#endif17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口2.6.1程序设计(2)uart.c设计串行口源文件“uart.c”内容如下:sfrSCON=0x98;sfrSBUF=0x99;sfrAUXR=0x8e;sfrT2L=0xd7;sfrT2H=0xd6;sbitTI=SCON^1;sbitRI=SCON^0;

17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口2.6.1程序设计(2)uart.c设计voidUart_Init(void) //9600bps@12.000MHz{SCON=0x50; //8位数据,可变波特率AUXR|=0x01; //串行口1选择定时器2为波特率发生器AUXR|=0x04; //定时器2时钟为Fosc,即1TT2L=0xC7; //设定定时初值T2H=0xFE; //设定定时初值AUXR|=0x10; //启动定时器2}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口2.6.1程序设计(2)uart.c设计voidUart_SendChar(unsignedcharc){SBUF=c;while(TI==0);TI=0;}charputchar(charc) //printf()调用{Uart_SendChar(c);returnc;}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口2.6.1程序设计(2)uart.c设计unsignedcharucUart_Dly; //串行口接收字符延时externunsignedcharpucUart_Buf[10]; //串行口缓存externunsignedcharucUart_Num; //串行口接收字符计数voidUart_RecvString(void){if(RI){pucUart_Buf[ucUart_Num++]=SBUF;RI=0;ucUart_Dly=0; //开始计时}17:35:20单片机设计与开发第2章模块程序设计前页

返回2.6串行口2.6.1程序设计(2)uart.c设计if((ucUa

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论