单片机c语音自定义标志位用法Bit

上传人:平*** 文档编号:16048050 上传时间:2017-11-06 格式:DOC 页数:10 大小:75.07KB
返回 下载 相关 举报
单片机c语音自定义标志位用法Bit_第1页
第1页 / 共10页
单片机c语音自定义标志位用法Bit_第2页
第2页 / 共10页
单片机c语音自定义标志位用法Bit_第3页
第3页 / 共10页
单片机c语音自定义标志位用法Bit_第4页
第4页 / 共10页
单片机c语音自定义标志位用法Bit_第5页
第5页 / 共10页
点击查看更多>>
资源描述

《单片机c语音自定义标志位用法Bit》由会员分享,可在线阅读,更多相关《单片机c语音自定义标志位用法Bit(10页珍藏版)》请在金锄头文库上搜索。

1、单片机 C 语言编程中“位”(bit) 的保存方案引言在现有的教课书及相关文章中,都难得提到在单片机 C 语言编程中对于自定义“位”的状态进行保存的理念。当单片机 C 语言编程中提及“位”的概念时,人们自然会想到状态字 PSW中 PSW.5 的 F0 与 PSW.1 的 F1 两个用户通用标志位。这两个标志位均可参与布尔运算、“位”控操作,也可随状态字 PSW 一起保存。但是,往往会忽视这一点:在一些特定的情况下,如在 C 语言编程的中断服务程序中,对状态字 PSW中 PSW.5 的 F0 与 PSW.1 的 F1 这两个用户标志位的操作可能是无效的。如:void EX1_ISR() inte

2、rrupt 2 /外部中断 1static unsigned int tempaddr;/定义接收地址缓存static unsigned int tempkey;/定义接收数据缓存unsigned int timecnt;timecnt=TH1*256+TL1;TH1=0;TL1=0;TR1=1;/定时器 1 启动F0=F0;/取反 F0if(F0) tempaddr=tempaddr1;else tempkey=tempkey1;以上是一段单片机外部中断 1 的中断服务程序,乍看似乎没什么问题,仿真调试时也能通过“编辑”。但实际上这是一段错误的程序其中对“F0”用户标志位的“取反”操作是达不

3、到其预期效果的。因为对“F0”用户标志位的“取反”操作是在中断服务程序中进行的。在进入中断时,C 语言自动会保护“中断现场”将程序指针 PC、累加器 ACC、状态字 PSW 等压入堆栈保护起来直到中断返回时弹出堆栈并覆盖了中断服务时的变值,恢复到压入堆栈之前的原样。因此,状态字 PSW 中的 F0 也不例外,如果压入堆栈之前 F0 是处于逻辑“0”状态,中断返回后还是复原成逻辑“0”状态不管中断服务程序中怎么取反改变也就是说,在中断服务程序中试图改变 F0 之值的操作是有失偏颇的。对于上文例举的那段中断服务程序来说,若 F0 的初始状态为逻辑“0”,即进入中断服务之前和中断返回之后总是逻辑“0

4、”,那么进入执行“F0=F0”指令后 F0 总是逻辑“1”,因而接下运行的是“if(F0)”下花括号中“tempaddr=tempaddr1;”指令,而“else”下花括号中“tempkey=tempkey1”指令永远也运行不到。所以,若要中断服务程序达到预期的效果“if(F0)”下花括号中的指令与“else”下花括号中的指令轮番运行,必须设立一个不受中断现场保护等影响的自定义标志位。1 自定义标志“位”的保存在 C 语言编程中,自定义标志位的运用概率很大,有的一个程序中就会有好多的自定义标志位,且其中几个可能是必须要保存的。譬如有些控制器件中对一些控制状态进行保持,即使是停电之后再来电了这种

5、控制状态依然能保持不变这就牵涉到保存问题。例举 2:我们曾搞过一个镭射投影屏幕升降的无线遥控装置。这个以单片机为核心的控制装置与屏幕升降的卷动电机等都安装固定在一个直径不足 50 mm 的狭长铁桶里面,因此装入或拆卸都非常麻烦。为了一次性成功避免再次拆卸装入的麻烦,在用 C 语言编程时我特意多用了一个自定义的标志位翻转标志位“switch_sign”。因为无线遥控手柄上的向上“”、暂停“”、向下“”的键标志都已是做定的,因此,如果由于接线等失误导致按向下“”键时投影屏幕向上卷、按向上“”键时投影屏幕却向下伸有了“switch_sign”自定义的标志位就不用怕这些了。相关的 C 语言程序段如下:

6、#defineuint unsigned int#defineuchar unsigned charuint Decode_addr,Decode_key,addr;sbit JD1_out=P04;/定义继电器 1 控制输出端sbit JD2_out=P05;/定义继电器 2 控制输出端sbit BEEP=P03;/定义蜂鸣声响输出bit bdata switch_sign;/自定义的翻转标志位(应作全局变量定义)voidTelecontrol_Data() if(Decode_addr=0x5535) /地址码核对if(Decode_key=0x00C0) /“”键码核对BEEP=1;/蜂

7、鸣声响输出if(switch_sign) /翻转标志位JD1_out=0;/继电器 1 控制输出端JD2_out=1; /继电器 2 控制输出端else JD1_out=1;/继电器 1 控制输出端JD2_out=0;/继电器 2 控制输出端if(Decode_key=0x0030) /“”键码核对BEEP=1;/蜂鸣声响输出JD1_out=0;/继电器 1 控制输出端JD2_out=0;/继电器 2 控制输出端if(Decode_key=0x000C) /“”键码核对BEEP=1;/蜂鸣声响输出if(switch_sign) /翻转标志位JD1_out=1;/继电器 1 控制输出端JD2_o

8、ut=0;/继电器 2 控制输出端else JD1_out=0;/继电器 1 控制输出端JD2_out=1;/继电器 2 控制输出端if(Decode_addr=0x5D35) /取反操作纠正时地址码核对if(Decode_key=0x00C0) /“”键码核对BEEP=1;/蜂鸣声响输出switch_sign=switch_sign; /取反一次翻转标志位save_data();/调用保存数据子程序从上面这段遥控数据处理子程序可以看到:在任何时候两个继电器的控制输出端 JD1_out 与 JD2_out 至多只能开一个。当遥控“”键按下有效时,翻转标志位“switch_sign”的逻辑“0”

9、或逻辑“1”状态将决定两个继电器的控制输出端 JD1_out 与 JD2_out 的一开一关,或一关一开;同理,当遥控“”键按下有效时也会得到与“”键按下相反的类同效果也就是说,只要改变翻转标志位“switch_sign”的逻辑状态,就能改变两个继电器控制输出端谁“开”谁“关”的控制输出状态。亦即,在同一个遥控按键按下时(如“”键按下),标志位“switch_sign”的逻辑状态不同,两个继电器控制输出端谁“开”谁“关”的控制输出状态也将不同。其中的蜂鸣声响提示按键操作是否有效。投影屏幕升降的动力电机是一个 AC 220V 的交流电机,图 1 是电机控制电路的简图。由此可见,当继电器 JD1

10、闭合,JD2 断开时,电机 M 中的 L1 为主绕组,L2 为启动副绕组,电机将一个方向运转;当继电器 JD1 断开,JD2 闭合时,电机 M 中的 L1 为启动副绕组,而 L2 为主绕组了,电机将以原来的反方向运转。结合上文,改变翻转标志位“switch_sign”的逻辑状态改变两个继电器控制输出端谁“开”谁“关”的控制输出状态改变电机的运转方向投影屏幕的升降状态。也就是说,改变翻转标志位“switch_sign”的逻辑状态,就可纠正遥控电机运转方向及其投影屏幕的升降状态。将遥控按键与投影屏幕升降的对应关系协调后,必须保存自定义的标志位“switch_sign”当前的逻辑状态,否则,断电后下

11、一次上电复位初始化,又可能要出洋相了。从例举 2 的程序中还可以看到,翻转标志位“switch_sign”的取反操作也是用同一个遥控器上的“”键来执行的,只是在遥控器的地址编码上动了点手脚改变了一下地址编码(0x5D35),待操作对应协调后再改回到原来的地址编码(0x5535)。2 保存 1 个字节来复原自定义标志“位”自定义标志“位”的保存及其复原有很多种方法,我曾尝试过几种方法。例 3 是一种保存 1 个字节来复原 1 个自定义标志位的方法,具体操作如下:static unsigned char current_dat;/定义一个通用的辅助字节变量bit bdata switch_sign

12、;/自定义的翻转标志位(应作全局变量定义)switch_sign=switch_sign;/取反 1 次翻转标志位if(switch_sign) /判断 switch_sign 是逻辑“1”还是逻辑“0”current_dat=0xA5;/对通用的辅助字节变量赋值else current_dat=0x00;/通用的辅助字节变量save_data();/调用保存数据子程序BEEP=1;/蜂鸣声响输出以上程序是:取反翻转标志位“switch_sign”后,若“switch_sign”为逻辑“1”状态,就给通用的辅助字节变量“current_dat”赋值“0xA5”(当然,这数据由你自己随意定);若

13、“switch_sign”为逻辑“0”状态,则给通用的辅助字节变量“current_dat”赋值“0x00”(这数据也是自己随意定的,只要与前面那个不一样就是了),然后调用保存数据程序将通用的辅助字节变量“current_dat”保存起来。这样,即使断电了翻转标志位“switch_sign”的当前状态已间接地被通用的辅助字节变量“current_dat”保存起来了当下一次上电复位初始化时,应先将保存的辅助变量“current_dat”的数据读出来,并还原成翻转标志位“switch_sign”相应的逻辑状态。上电初始化时若从存储处读出的数据是“0xA5”,则将翻转标志位“switch_sign”

14、置“1”;若读出的数据是“0x00”,则将翻转标志位“switch_sign”置“0”这就与原来保存时的状态对应起来了。其操作过程如例 4:static unsigned char current_dat;/定义一个通用的辅助字节变量static unsigned char addr;/自定义地址变量缓冲单元static unsigned char Rdat;/自定义读数据缓冲单元bit bdata switch_sign;/自定义的翻转标志位(应作全局变量定义)addr=0x7F6;/给一个原来的存储地址REEPROM();/调用读取 E2PROM 的子程序current_dat=Rdat;

15、/将读出的数据还给通用的辅助字节变量if(current_dat=0xA5) /判断读出的数据是否等于“0xA5”switch_sign=1;/将翻转标志位“switch_sign”置“1”else switch_sign=0;/将翻转标志位“switch_sign”置“0”31 个字节保存 8 个自定义“位”用保存一个自定义的字节变量来复原一个自定义标志位的过程上文已叙述了,接下来阐述 1 个字节变量保存 8 个自定义“位”的方案。1 个字节变量保存 8 个自定义“位”的方案很多,例 5 是其中比较理想的一种:#defineuint unsigned int#defineuchar unsigned charuintaddr;ucharWdat,Rdat;uchar bdatacurrent_dat;/在可位寻址区定义 unsigned char 类型的字节变量 current_datsbitsign_bit1= current_dat0;/用关键字 sbit 定义位变量来独立访问可寻址位对象中的 1 位sbitsign_bit2= current_dat1;/自定义标志位 2sbitsign_bit3= current_dat2;/自定义标志位 3sbitsign_bit8= current_dat7;/自定义标志位 8vo

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 其它办公文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号