MSP430单片机实用技术讲座13第9讲简单的端口显示中断综合应用
- 格式:pdf
- 大小:363.05 KB
- 文档页数:2
MSP430单片机实用技术讲座(13) 第9讲 简单的端口、显示、中断综合应用・南京航空航天大学 魏小龙・本讲将结合定时器、端口、中断等430资源进行综合应用。
具体要求如下:1.硬件连接 硬件连接(如图1)很简单,在P4端口连接了8只发光二极管LED0 ̄LED7,在P1端口连接了4×4键盘(16键)。
P1同时通过138、164扩展了8位数码显示器。
2.软件要求a)编写扫描键盘软件;b)编写数码管显示程序;c)键盘使用中断编写;d)P4连接的发光二极管的发光强度通过键盘控制,共分16亮度等级;e)分别控制单个发光二极管(可对LED0到LED7进行分别控制其亮度);f)在数码管上显示每只发光二极管的亮度,对应关系为:第一只数码管显示的数值对应第一只发光二极管的亮度,后面依次类推,第八只数码管显示的数值对应第八只发光二极管的亮度。
3.分析首先编写基本硬件程序,键盘与数码管显示已经在上一讲说清楚了,这里只管调用就可以了。
发光二极管显示也很简单,高电平亮,低电平熄。
那么如何实现发光二极管LED0 ̄ LED7显示的亮暗调节呢。
先看看图2所示的4个不同信号a、b、c、d。
假设它们的周期都是100Hz,则这些信号送发光二极管后,我们看不到发光二极管的亮与熄,我们看到的都是亮,只不过亮度不一样而已(因为人眼睛的视觉暂停缘故)。
很显然,信号a驱动发光二极管最暗,信号d驱动发光二极管最亮。
本讲所使用的硬件有16只扫描键盘,我们定义按0号按键显示最暗,按F号按键显示最亮。
根据软件要求e要求分别控制单个发光二极管(可对LED0到LED7进行分别控制其亮度),那么如何实现呢?我们可以将亮度数据存放在显示缓存里,则disbuffer[0]的数据表示LED0的亮度, 则disbuffer[1]的数据表示LED1的亮度......这样只要在显示缓存中取对应的亮度数值去控制发光二极管的显示就可以了。
数码管的显示方法为:在显示缓存中取数据移位到驱动对应数码管的74HC164,并延时显示一会儿。
系统复位、中断及工作模式-利尔达MSP430培训资料系统复位、中断及工作模式嵌入式研发中心复位电路的结构POR(Power-on reset)的产生:上电 RST出现低电平 SVS产生复位动作 PUC(Power-up clear)的产生: POR信号 WDT时间溢出看门狗密钥错误 FLASH操作密钥错误 BOR(Brownout Reset)的产生: BOR 模块产生 PUC BOR PORBOR时序POR和BORBOR: MCLK< 4Mhz Brown-out!系统复位后的状态RSR/NMI为复位状态 IO口为输入状态各模块和寄存器恢复为初始化的状态状态寄存器SR复位看门狗WDT为看门狗状态 FFFE的内容装入PC指针软件必须完成的工作初始化堆栈指针SP,一般为RAM的顶端根据应用的需要,初始化WDT 对模块初始化特别注意:看门狗、晶振失败、FLASH写入失败都可以引起 RESET复位电路的设计1. RESET脚直接通过电阻上拉----不建议采用此方式2. RESET脚采用RC复位电路3. RESET脚采用电压监控芯片适用于MSP430没有BOR电路的芯片可以确保用户控制器中满足所有的工作电压条件MCU才启动4. MSP430F20xx的RESET与SBW共用,电容不要过大Device Pins Flash/RA Timers Communicatio BOR Features M n F11x1 20 4k/256 A3 Comp_A 8k/256 A3 ADC10 F11x2 20 F12x 28 8k/256 A3 Comp_A USART F12x2 28 8k/256 A3 USART ADC10 F13x 64 16k/512 A3,B3 USART ADC12 F14x 64 60k/2k A3,B7(2)USART ADC12, MPY 64 32k/1k A3,B3 USART, I2C ADC12, (2)DAC12, (3)DMA F15x F16x 64 60k/10k A3,B7 (2)USART, ADC12, (2)DAC12, (3)DMA I2C All devices include watchdog timer (WDT) and basic clock system (BCS)MSP430中断种类系统复位 POR、PUC、BOR和SVS 非屏蔽中断NMI 晶振失败 FLASH失败可屏蔽中断 TA、BT、COMP、UART等中断矢量结构中断进入进入中断需要6个指令周期1. 当前运行的指令完成,PC指向下一条指令 2. PC压栈 3. SR压栈 4. 选择高优先级中断 5. 单元中断中断标志清除,多元中断需要软件清除 6. 除SCG0外,SR被清除,如果是低功耗,退出低功耗,GIE的清除关闭可屏蔽中断7.装载PC指针中断前中断后特别注意:进入中断后,SP指针指向堆栈中的SR. 可以在中断程序中修改0(SP)内容改变中断返回后 SR状态。
单片机中中断接口的工作原理及其使用技巧中断是单片机中重要的功能之一,它通过中断请求信号实现对处理器的打断,并进行相应的处理。
中断接口是单片机与外部设备之间的一个桥梁,它能够实现外部设备向单片机发送中断请求,并在适当的时候进行相应的处理。
本文将介绍中断接口的工作原理以及一些使用技巧。
中断接口的工作原理主要涉及到中断请求的产生、中断控制器的处理以及中断向量表的使用。
首先,中断请求的产生是由外部设备引脚向单片机发送中断请求信号实现的。
外部设备发出中断请求信号会引起中断控制器的检测,中断控制器会判断是否有高优先级的中断请求,如果有,则将中断请求信号传递给处理器;如果没有,则忽略中断请求。
其次,中断控制器是中断接口的核心部分,它根据中断请求的优先级和处理器的处理能力,对中断请求进行筛选和分配。
中断控制器通常包括一个中断请求优先级编码器、中断屏蔽寄存器和中断嵌套机制等。
中断请求优先级编码器用于对中断请求进行优先级编码,以便进行屏蔽和分配。
中断屏蔽寄存器用于设置允许处理器接受哪些中断请求。
中断嵌套机制允许在处理一个中断的过程中,另一个优先级更高的中断请求打断当前中断的处理。
最后,中断向量表是用来存储中断服务程序入口地址的,当处理器接收到中断请求后,会根据中断请求的编号在中断向量表中查找相应的中断服务程序入口地址,并跳转到该地址开始执行中断服务程序。
中断向量表通常是一个固定的内存地址范围,每个中断请求有一个对应的中断服务程序入口地址。
在使用中断接口时,有几点需要注意的技巧:首先,合理设置中断优先级。
不同的中断请求可能具有不同的优先级,它们的触发时机和紧迫程度也不同。
根据实际需求,应合理设置中断的优先级,确保高优先级的中断请求能够及时处理。
其次,有效利用中断屏蔽寄存器。
中断屏蔽寄存器可以屏蔽一些不必要的中断请求,以提高系统性能和响应速度。
但是要注意,在屏蔽某些中断请求时,确保不会丢失重要的中断信号。
此外,中断服务程序的编写也是一个关键的环节。
数码管也是单片机系统最常用的输出设备之一(还有液晶、发光二极管等)。
七段(这里用的是8段,有小数点)数码管可以完成显示0-9数字和一部分的英文字符如:A、b。
本文实现的程序完成显示数字和可显示的英文字符;同时完成数码管显示的printf函数的移植,以支持printf的格式化字符等好用的特点(我用的数码管8个排为一排,方便数字等的显示)。
1.硬件介绍:这里所用到的硬件资源包括8个数码管、和msp430单片机的两个8位IO口(这里用的是P3和P5口,如有改变,可以通过宏定义更改)。
数码管是8个共阴的数码管,a-h8段通过一个200Ω的电阻接到430单片机的P5口。
共阴端是由单片机的P3口控制,单片机的一位IO通过一个三极管接到数码管的共阴端,以完成位选。
单片机的P3口时数码管的位选口,某位为高则选中;P5口时段选口;要数码管显示时,通过P3位选,选中某个数码管亮,P5段选选择8段(a-h)中的那些亮,从而控制某一位显示数字或字符。
要同时显示多个数码管,就要动态扫描;动态扫描时,本程序选用的是由看门狗的中断扫描显示:每1.9ms显示其中的一位,动态扫描显示每一位,从而让数码管看起来是同时亮的。
2.程序实现:数码管显示首先要有一个数码管显示的断码表(完成数字和字符到数码管段值的表),程序中采用了《MSP430系列单片机系统工程设计与实践》这本书推荐的方式实现的这个数码表:先用宏定义定义每段对应的单片机要输出的段值,然后再实现是个表,当硬件改变时,只需更改前面的每段的段值定义即可,改动的地方少了很多,代码如下:/*宏定义,数码管a-h各段对应的比特,更换硬件只用改动以下8行*/#define a0x01//AAAA#define b0x02//F B#define c0x04//F B#define d0x08//GGGG#define e0x10//E C#define f0x20//E C#define g0x40//DDDD HH#define h0x80//小数点/*用宏定义自动生成段码表,很好的写法,值得学习*//*更换硬件无需重写段码表*/const char Tab[]={a+b+c+d+e+f,//Displays"0"b+c,//Displays"1"a+b+d+e+g,//Displays"2"a+b+c+d+g,//Displays"3"b+c+f+g,//Displays"4"a+c+d+f+g,//Displays"5"a+c+d+e+f+g,//Displays"6"a+b+c,//Displays"7"a+b+c+d+e+f+g,//Displays"8"a+b+c+d+f+g,//Displays"9"a+b+c+e+f+g,//Displays"A"c+d+e+f+g,//Displays"B"a+d+e+f,//Displays"C"b+c+d+e+g,//Displays"D"a+d+e+f+g,//Displays"E"a+c+d+e+f,//Displays"G" b+c+e+f+g,//Displays"H" e+f,//Displays"I" b+c+d+e,//Displays"J" b+d+e+f+g,//Displays"K" d+e+f,//Displays"L" a+c+e+g,//Displays"M" a+b+c+e+f,//Displays"N" c+e+g,//Displays"n" c+d+e+g,//Displays"o" a+b+c+d+e+f,//Displays"O" a+b+e+f+g,//Displays"P" a+b+c+f+g,//Displays"Q" e+g,//Displays"r" a+c+d+f+g,//Displays"S" d+e+f+g,//Displays"t" a+e+f,//Displays"T" b+c+d+e+f,//Displays"U" c+d+e,//Displays"v" b+d+f+g,//Displays"W" b+c+d+f+g,//Displays"Y"g,//Displays"-"h,//Displays"."0//Displays"" };#undef a#undef b#undef c#undef d#undef e#undef f#undef g0-9的位置对应显示0-9,之后的是A开始往后显示,为了方便访问这个表格,定义了AA等一系列的常量,方便访问这个表。
端口1中断函数多中断中断源:P1IFG.0~P1IFG7进入中断后应首先判断中断源,退出中断前应清除中断标志,否则将再次引发中断#pragma vector=PORT1_VECTOR__interrupt void Port1(){ //以下为参考处理程序,不使用的端口应当删除其对于中断源的判断。
if((P1IFG&BIT0) == BIT0){ //处理P1IN.0中断P1IFG &= ~BIT0; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT1) ==BIT1){//处理P1IN.1中断P1IFG &= ~BIT1; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT2) ==BIT2){//处理P1IN.2中断P1IFG &= ~BIT2; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT3) ==BIT3){//处理P1IN.3中断P1IFG &= ~BIT3; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT4) ==BIT4){//处理P1IN.4中断P1IFG &= ~BIT4; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT5) ==BIT5){//处理P1IN.5中断P1IFG &= ~BIT5; //清除中断标志//以下填充用户代码}else if((P1IFG&BIT6) ==BIT6){//处理P1IN.6中断P1IFG &= ~BIT6; //清除中断标志//以下填充用户代码}else{//处理P1IN.7中断P1IFG &= ~BIT7; //清除中断标志//以下填充用户代码}}端口2中断函数多中断中断源:P2IFG.0~P2IFG7进入中断后应首先判断中断源,退出中断前应清除中断标志,否则将再次引发中断*****************************************************************************/ #pragma vector=PORT2_VECTOR__interrupt void Port2(){//以下为参考处理程序,不使用的端口应当删除其对于中断源的判if((P2IFG&BIT0) == BIT0){//处理P2IN.0中断P2IFG &= ~BIT0; //清除中断标志//以下填充用户代码}else if((P2IFG&BIT1) ==BIT1){//处理P2IN.1中断P2IFG &= ~BIT1; //清除中断标志//以下填充用户代码 }else if((P2IFG&BIT2) ==BIT2){//处理P2IN.2中断 P2IFG &= ~BIT2; //清除中断标志//以下填充用户代码 }else if((P2IFG&BIT3) ==BIT3){//处理P2IN.3中断 P2IFG &= ~BIT3; //清除中断标志//以下填充用户代码}else if((P2IFG&BIT4) ==BIT4){//处理P2IN.4中断P2IFG &= ~BIT4; //清除中断标志//以下填充用户代码 }else if((P2IFG&BIT5) ==BIT5){//处理P2IN.5中断P2IFG &= ~BIT5; //清除中断标志//以下填充用户代码}else if((P2IFG&BIT6) ==BIT6){//处理P2IN.6中断P2IFG &= ~BIT6; //清除中断标志//以下填充用户代码}else{//处理P2IN.7中断P2IFG &= ~BIT7; //清除中断标志//以下填充用户代码}}USART0发送中断函数******************************************************************************/ #pragma vector=USART0TX_VECTOR__interrupt void Usart0Tx(){//以下填充用户代码}USART0接收中断函数******************************************************************************/ #pragma vector=USART0RX_VECTOR__interrupt void Usart0Rx(){//以下填充用户代码}USART1发送中断函数******************************************************************************/ #pragma vector=USART1TX_VECTOR__interrupt void Usart1Tx(){//以下填充用户代码}SART1接收中断函数******************************************************************************/ #pragma vector=USART1RX_VECTOR__interrupt void Ustra1Rx(){//以下填充用户代码}基本定时器中断函数******************************************************************************/ #pragma vector=BASICTIMER_VECTOR__interrupt void BasTimer(){//以下填充用户代码}定时器A中断函数多中断中断源:CC1~2 TA******************************************************************************/#pragma vector=TIMER0_A1_VECTOR__interrupt void TimerA1(){//以下为参考处理程序,不使用的中断源应当删除switch (__even_in_range(TAIV, 10)){case 2: //捕获/比较1中断//以下填充用户代码break;case 4: //捕获/比较2中断//以下填充用户代码break;case 10: //TAIFG定时器溢出中断//以下填充用户代码break;}}定时器A中断函数中断源:CC0******************************************************************************/ #pragma vector=TIMERA0_VECTOR__interrupt void TimerA0(){//以下填充用户代码}多中断源:CC1~6 TB******************************************************************************/ #pragma vector=TIMERB1_VECTOR__interrupt void TimerB1(){//以下为参考处理程序,不使用的中断源应当删除switch (__even_in_range(TBIV, 14)){case 2: //捕获/比较1中断//以下填充用户代码break;case 4: //捕获/比较2中断//以下填充用户代码break;case 6: //捕获/比较3中断//以下填充用户代码break;case 8: //捕获/比较4中断//以下填充用户代码break;case 10: //捕获/比较5中断//以下填充用户代码break;case 12: / /捕获/比较6中断//以下填充用户代码break;case 14: //TBIFG定时器溢出中断//以下填充用户代码break;}}中断源:CC0******************************************************************************/ #pragma vector=TIMERB0_VECTOR__interrupt void TimerB0(){//以下填充用户代码}AD转换器中断函数多中断源:摸拟0~7、VeREF+、VREF-/VeREF-、(AVcc-AVss)/2 没有处理ADC12TOV和ADC12OV中断标志******************************************************************************/ #pragma vector=ADC_VECTOR__interrupt void Adc(){//以下为参考处理程序,不使用的中断源应当删除if((ADC12IFG&BIT0)==BIT0){ //通道0//以下填充用户代码}else if((ADC12IFG&BIT1)==BIT1){ //通道1//以下填充用户代码}else if((ADC12IFG&BIT2)==BIT2){ //通道2//以下填充用户代码}else if((ADC12IFG&BIT3)==BIT3){ //通道3//以下填充用户代码}else if((ADC12IFG&BIT4)==BIT4){ //通道4//以下填充用户代码}else if((ADC12IFG&BIT5)==BIT5){ //通道5//以下填充用户代码}else if((ADC12IFG&BIT6)==BIT6){ //通道6//以下填充用户代码}else if((ADC12IFG&BIT7)==BIT7){ //通道7//以下填充用户代码 }else if((ADC12IFG&BIT8)==BIT8){ //VeREF+//以下填充用户代码 }else if((ADC12IFG&BIT9)==BIT9){ //VREF-/VeREF-//以下填充用户代码}else if((ADC12IFG&BITA)==BITA){ //温度//以下填充用户代码}else if((ADC12IFG&BITB)==BITB){ //(A Vcc-A Vss)/2//以下填充用户代码}}看门狗定时器中断函数******************************************************************************/ #pragma vector=WDT_VECTOR__interrupt void WatchDog(){//以下填充用户代码}比较器A中断函数******************************************************************************/ #pragma vector=COMPARA TORA_VECTOR__interrupt void ComparatorA(){//以下填充用户代码}不可屏蔽中断函数******************************************************************************/ #pragma vector=NMI_VECTOR__interrupt void Nmi(){//以下为参考处理程序,不使用的中断源应当删除if((IFG1&OFIFG)==OFIFG){ //振荡器失效IFG1 &= ~OFIFG;//以下填充用户代码}else if((IFG1&NMIIFG)==NMIIFG){ //RST/NMI不可屏蔽中断IFG1 &= ~NMIIFG;//以下填充用户代码}else //if((FCTL3&ACCVIFG)==ACCVIFG){ //存储器非法访问FCTL3 &= ~ACCVIFG;//以下填充用户代码}}中断优先级:优先级顺序从高到低为:PORT2_VECTOR (1 * 2u) /* 0xFFE2 Port 2 */PORT1_VECTOR (4 * 2u) /* 0xFFE8 Port 1 */TIMER0_A1_VECTOR (5 * 2u) /* 0xFFEA Timer A CC1-2, TA */TIMER0_A0_VECTOR (6 * 2u) /* 0xFFEC Timer A CC0 */ADC_VECTOR (7 * 2u) /* 0xFFEE ADC */USART0TX_VECTOR (8 * 2u) /* 0xFFF0 USART 0 Transmit */USART0RX_VECTOR (9 * 2u) /* 0xFFF2 USART 0 Receive */WDT_VECTOR (10 * 2u) /* 0xFFF4 Watchdog Timer */ COMPARATORA_VECTOR (11 * 2u) /* 0xFFF6 Comparator A */TIMERB1_VECTOR (12 * 2u) /* 0xFFF8 Timer B CC1-2, TB */TIMERB0_VECTOR (13 * 2u) /* 0xFFFA Timer B CC0 */NMI_VECTOR (14 * 2u) /* 0xFFFC Non-maska××e */RESET_VECTOR (15 * 2u) /* 0xFFFE Reset [Highest Priority] */。
单片机中断原理及应用单片机中断是一种重要的编程技术,它在嵌入式系统中起到关键作用。
本文将介绍单片机中断的原理以及在实际应用中的一些常见用法。
一、中断的原理中断是一种在程序执行期间由外部事件引发的特殊信号,它会打断正常的程序流程,跳转到中断处理程序进行相应的处理。
单片机中断可以通过硬件或软件触发,根据中断优先级的不同,可以采用优先级编码或轮询方式进行中断请求的处理。
硬件中断通常由外部事件引起,例如按键按下、定时器溢出、串口数据接收等。
当这些事件发生时,单片机会发出中断请求信号,并保存当前的执行状态,然后跳转到相应的中断服务程序进行处理。
处理完毕后,单片机会恢复到被中断的位置继续执行。
软件中断是通过执行特殊的指令触发,常用于在程序中主动请求中断。
软件中断一般用于实现程序间的通信、任务调度等功能。
二、中断的应用1. 外部中断外部中断是单片机中最常见的中断类型之一,它可以响应外部事件的触发。
例如,当用户按下按键时,就可以通过外部中断实现按键检测并进行相应的处理。
外部中断通常用于实现外设的输入功能,如按钮检测、触摸屏输入等。
在外部中断的应用中,首先需要配置外部中断引脚的触发方式和中断服务程序。
当外部事件触发时,单片机会跳转到中断服务程序中执行相应的操作。
在中断服务程序中,可以对输入信号进行处理,如检测按键是否按下、读取触摸屏坐标等,然后根据需求进行相应的响应或操作。
2. 定时器中断定时器中断是单片机中另一个常见的中断类型。
通过定时器中断,可以实现精确的定时任务,如测量时间间隔、产生定时脉冲等。
定时器中断通常用于实现系统时钟、延时、定时采样等功能。
在定时器中断的应用中,首先需要对定时器进行配置以及中断服务程序的编写。
在中断服务程序中,可以进行一系列与时间相关的操作,如更新系统时钟、执行定时任务、控制脉冲输出等。
3. 串口中断串口中断用于处理串口通信中的数据接收或发送中断事件。
单片机通过串口中断可以实现与外部设备的可靠通信,如与PC机的数据传输、与传感器的数据采集等。
MSP430与DS18B20数码管显示(中断法)#include ;typedef unsigned char uchar;typedef unsigned int uint;/*****18B20部分的接口定义********/#define DQ1 P1OUT |= BIT6#define DQ0 P1OUT &= ~BIT6#define DQ_inP1DIR &= ~BIT6#define DQ_out P1DIR |= BIT6#define DQ_val (P1IN & BIT6)/*****数码管部分的接口定义********/#define wei_h P5OUT|= BIT5#define wei_l P5OUT&= ~BIT5#define duan_lP6OUT &= ~BIT6#define duan_h P6OUT |= BIT6//数码管七段码;0--fuchar table[16] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; uchar table1[16] ={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xf7,0xfc,0xb9,0xde,0xf9,0xf1};//有点uchar tflag,num=0 ;int tvalue;uchar disdata[4];/***********18B20部分程序******************//*******************************************函数名称:DelayNus功能:实现N个微秒的延时参数:n--延时长度返回值:无说明:定时器A的计数时钟是1MHz,CPU主频8MHz所以通过定时器延时能够得到极为精确的us级延时********************************************/ void DelayNus(uint n){CCR0 = n;TACTL |= MC_1;//增计数到CCR0while(!(TACTL & BIT0));//等待TACTL &= ~MC_1;//停止计数TACTL &= ~BIT0;//清除中断标志}/******************************************* 函数名称:Init_18B20功能:对DS18B20进行复位操作参数:无返回值:初始化状态标志:1--失败,0--成功********************************************/ uchar Init_18B20(void){uchar Error;DQ_out;_DINT();DQ0;DelayNus(500); DQ1;DelayNus(55); DQ_in;_NOP();if(DQ_val){Error = 1;//初始化失败}else{Error = 0;//初始化成功}DQ_out;DQ1;_EINT();DelayNus(400);return Error;//此处如果 Error = 1,后面就会出现死循环,表示18B20可能坏了}/*******************************************函数名称:Write_18B20功能:向DS18B20写入一个字节的数据参数:wdata--写入的数据返回值:无********************************************/ void Write_18B20(uchar wdata){uchar i;_DINT();for(i = 0; i ;>;= 1;DelayNus(50);//延时50usDQ1;DelayNus(10);//延时10us}_EINT();}/******************************************* 函数名称:Read_18B20功能:从DS18B20读取一个字节的数据参数:无返回值:读出的一个字节数据********************************************/ uchar Read_18B20(void){uchar i;uchar temp = 0;_DINT();for(i = 0;i ;>;= 1; DQ0;DelayNus(6);//延时6usDQ1;DelayNus(8);//延时9usDQ_in;_NOP();if(DQ_val)temp |= 0x80;DelayNus(45); //延时45usDQ_out;DQ1;DelayNus(10); //延时10us}_EINT();return temp;}uint Do1Convert(void) {uchar i;uchar temp_low; uint temp;do{i = Init_18B20();}while(i);//此处的i就是等于前面的Error,Error = 1,就会出现死循环,表示18B20可能坏了Write_18B20(0xcc);//送跳过读取产品ID号命令Write_18B20(0x44);//发送温度转换命令for(i = 20;i >; 0;i--)DelayNus(60000); //延时800ms以上do{i = Init_18B20();}while(i);//此处的i就是等于前面的Error,Error = 1,就会出现死循环,表示18B20可能坏了Write_18B20(0xcc);//送跳过读取产品ID号命令 Write_18B20(0xbe);//发送读ROM命令temp_low = Read_18B20();//读低位temp = Read_18B20();//读高位temp = (temp; 0; i--);//等待8MHz晶体起振}while ((IFG1 & OFIFG));//晶振失效标志仍然存在?BCSCTL2 |= SELM_2 + SELS;//MCLK和SMCLK选择高频晶振/*P6DIR |= BIT6;P6OUT |= BIT6;//关闭电平转换P5DIR |= BIT5;P5OUT |= BIT5;//关闭电平转换P6DIR |= BIT7;P6OUT |= BIT7; //关闭蜂鸣器*/ // 设置看门狗定时器,初始化控制数码管的IO WDTCTL = WDT_ADLY_1_9;IE1 |= WDTIE;//计数时钟选择SMLK=8MHz,1/8分频后为1MHz TACTL |= TASSEL_2 + ID_3;//打开全局中断_EINT();//循环读数显示while(1){display(Do1Convert());}}/*******************************************函数名称:watchdog_timer功能:看门狗定时器中断服务函数,进行数码管动态扫描参数:无返回值:无********************************************/#pragma vector = WDT_VECTOR__interrupt void watchdog_timer(void){P4OUT = table[disdata[num]];if(num==2) P4OUT = table1[disdata[num]]; //加上小数点duan_h;duan_l;P4OUT = ~(1<<num);//送出位码wei_h;wei_l;num++;if(num == 4) num = 0;}。
中国单片机世界-论坛 (/bbs/index.asp)-- 资料共享 (/bbs/list.asp?boardid=3)---- MSP430单片机实用技术讲座 (/bbs/dispbbs.asp?boardid=3&id=199)-- 作者:飞天-- 发布时间:2004-9-5 0:22:42-- MSP430单片机实用技术讲座以下内容只有回复后才可以浏览-- 作者:飞天-- 发布时间:2004-9-5 0:31:23--在运算速度方面,MSP430系列单片机能在8MHz晶体的驱动下,实现125μs的指令周期。
16位的数据宽度、125μs的指令周期以及多功能的硬件乘法器(能实现乘加)相配合,能实现数字信号处理的某些算法(如FFT等)。
MSP430系列单片机的中断源较多,并且可以任意嵌套,使用时灵活方便。
当系统处于省电的备用状态时,用中断请求将它唤醒只需6μs。
超低功耗MSP430单片机之所以有超低的功耗,是因为其在降低芯片的电源电压及灵活而可控的运行时钟方面都有其独到之处。
首先,MSP430系列单片机的电源电压采用的是1.8~3.6V电压。
因而可使其在1MHz的时钟条件下运行时,芯片的电流会在0.1~400μA之间。
其次,独特的系统时钟系统的设计。
在MSP430系列中有两种不同的系统时钟系统:基本时钟系统和锁频环(FLL和FLL+)时钟系统。
有的使用一个晶体振荡器(32768Hz),有的使用两个晶体振荡器(一个为32768Hz,另一个为高频振荡器)。
由系统时钟系统产生CPU和各功能模块所需的时钟。
并且这些时钟可以在指令的控制下,打开和关闭,从而实现对总体功耗的控制。
由于系统运行时打开的功能模块不同,即采用不同的工作模式,芯片的功耗有着显著不同。
在系统中共有一种活动模式(AM)和五种低功耗模式(LPM0~LPM4)。
在等待方式下,耗电为0.7A,在节电方式下,最低可达0.1A。
系统工作稳定上电复位后,首先由DCOCLK启动CPU,以保证程序从正确的位置开始执行,保证晶体振荡器有足够的起振及稳定时间。
MSP430单片机实用技术讲座(13)
第9讲 简单的端口、显示、中断综合应用
・南京航空航天大学 魏小龙・
本讲将结合定时器、端口、中断等430资源进行综合应用。
具体要求如下:
1.硬件连接 硬件连接(如图1)很简单,在P4端口连接了8只发光二极管LED0 ̄LED7,在P1端口连接了4×4键盘(16键)。
P1同时通过138、164扩展了8位数码显示器。
2.软件要求
a)编写扫描键盘软件;
b)编写数码管显示程序;
c)键盘使用中断编写;
d)P4连接的发光二极管的发光强度通过键盘控制,共分16亮度等级;
e)分别控制单个发光二极管(可对LED0到LED7进行分别控制其亮度);
f)在数码管上显示每
只发光二极管的亮度,对应关系为:第一只数码管显示的数值对应第一只发光二极管的亮度,后面依次类推,第八只数码管显示的数值对应第八只发光二极管的亮度。
3.分析
首先编写基本硬件程序,键盘与数码管显示已经在上一讲说清楚了,这里只管调用就可以了。
发光二极管显示也很简单,高电平亮,低电平熄。
那么如何实现发光二极管LED0 ̄ LED7显示的亮暗调节呢。
先看看图2所示的4个不同信号a、b、c、d。
假设它们的周期都是100Hz,则这些信号送发光二极管后,我们看不到发光二极
管的亮与熄,我们看到的都是亮,只不过亮度不一样而已(因为人眼睛的视觉暂停缘故)。
很显然,信号a驱动发光二极管最暗,信号d驱动发光二极管最亮。
本讲所使用的硬件有16只扫描键盘,我们定义按0号按键显示最暗,按F号按键显示最亮。
根据软件要求e要求分别控制单个发光二极管(可对LED0
到LED7进行分别控制其亮度),那么如何实现呢?我们可以将亮度数据存放在显示缓存里,则disbuffer[0]的数据表示LED0的亮度, 则disbuffer[1]的数据表示LED1的亮度......这样只要在显示缓存中取对应的亮度数值去控制发光二极管的显示就可以了。
数码管的显示方法为:在显示缓存中取数据移位到驱动对应数码管的74HC164,并延时显示一会儿。
这一讲的硬件共有8只数码管,需要8次移位与延时等待,而亮度等级有16级,所以可以使用两次移位,也就是显示程序再来一遍,构成16次。
这样可以将显示程序作为整个系统的主程序,发光二极管的亮度控制内嵌在显示程序中,则要将上一讲的显示程序进行改造。
同时需要注意键盘与显示程序的兼容性能,这一讲要求键盘使用中断,而显示与键盘合用口线,见图3、图4。
因为是合用口线,所以在显示程序中如果改变了键盘中断线的状态而满足了中断条件,则必然会进入中断,因为CPU认为是有按键了,从而进入了键盘中断,所以要避免这种情况。
具体方法:在显示程序中进行端口操作之前关闭中断,在端口操
作完成之后,清除端口的中断标志,然后打开中断。
只有在显示的延时显示时间段,键盘才可能中断。
这样就避免了显示程序对键盘的干扰,同时也实现了口线的合用。
很显然,显示程序可以直接作为整个程序的主循环!图5是显示程序的框图。
发光二极管显示对应亮度的程序思路:在显示程序中每显
图2
示一个数码管,变量con_time增1,则在显示程序的开始判断与控制发光二极管的显示亮度:如果第一个发光二极管的亮度值为1,则在显示程序的16次循环中只有第一次亮,如果第一个发光二极管的亮度值为5,则在显示程序的16次循环中只有前5次亮,其它都熄。
显示程序见本刊网站。
系统主程序很简单,首先初始化,然后主循环:调用显示程序。
显示程序同时用数码管显示各个发光二极管的亮度等级值与发光二极
管的不同亮度显示。
在显示的延时中等待键盘中断,输入参数。
◆
图5
图2
程序设计
主程序利用延时子程序产生矩形波序列,同频矩形波的个数和矩形波的脉宽通过中断服务程序来更新。
中断服务程序控制频率变化的方向,即频率升高和降低交替变化;利用修改T0中断时间常数重装来更新同频矩形波的延时时间;修改参数R1来更新不同频率矩形波频率。
图3为其程序流程图,在本刊的网站上给出了源程序,供读者参考。
系统调试
根据方案连接好电路,并在伟福51汇编环境下编程仿真调试,通过反复修改参数,使报警语音能够平滑地从低频到高频变化,周期控制在4秒时间左右,达到了预期的效果,相应实验参数如附表。
◆。