您的位置 首页 软件

第49节:使用DS18B20做一个温控器

开场白:DS18B20是一款常用的温度传感器芯片,它只占用单片机一根IO口,使用起来也特别方便。需要特别注意的是,正因为它只用一根IO口

开场白:
DS18B20是一款常用的温度传感器芯片,它只占用单片机一根IO口,运用起来也特别便利。需求特别注意的是,正因为它只用一根IO口跟单片机通讯,因而读取一次温度值的通讯时刻比较长,而且时序要求严厉,在通讯期间不答应被单片机其它的中止搅扰,因而在实践项目中,体系一旦选用了这款传感器芯片,就千万不要选用动态扫描数码管的显现方法。否则在封闭中止读取温度的时分,数码管的显现会有稍微的“闪耀”现象。
DS18B20的测温规模是-55度至125度。在-10度至85度的温度规模内差错是+-0.5度,能满意大部分常用的测温要求。
这一节要教会我们三个知识点:
榜首个:大约了解一下DS18B20的驱动程序。
第二个:做温控设备的时分,为了防止继电器在临界温度邻近频频跳动切换,应该设置一个缓冲温差。本程序的缓冲温差是2度。
第三个:持续加深了解按键,显现,传感器它们三者是怎么严密相关起来的程序结构。

具体内容,请看源代码解说。

(1) 硬件渠道.
依据朱兆祺51单片机学习板

(2)完成功用:
本程序只要1个窗口。这个窗口有2个部分显现。
第1个部分是第7,6,5位数码管,显现设定的温度。
第2个部分是第4,3,2,1位数码管,显现实践环境温度。其间第4位数码管显现正负符号位。
S1按键是加键,S5按键是减键。通过它们能够直接设置“设定温度”。
一个LED灯用来模仿工控的继电器。
当实践温度低于或许等于设定温度2度以下时,模仿继电器的LED灯亮。
当实践温度等于或许大于设定温度时,模仿继电器的LED灯灭。
当实践温度处于设定温度和设定温度减去2度的规模内,模仿继电器的LED保持现状,这个2度规模用来做缓冲温差,防止继电器在临界温度邻近频频跳动切换。

(3)源代码解说如下:

  1. #include “REG52.H”
  2. #define const_voice_short40 //蜂鸣器短叫的持续时刻
  3. #define const_key_time120 //按键去颤动延时的时刻
  4. #define const_key_time220 //按键去颤动延时的时刻
  5. #define const_ds18b20_sampling_time 180 //累计主循环次数的时刻,每次改写采样时钟芯片的时刻
  6. void initial_myself(void);
  7. void initial_peripheral(void);
  8. void delay_short(unsigned int uiDelayShort);
  9. void delay_long(unsigned int uiDelaylong);
  10. //驱动数码管的74HC595
  11. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);
  12. void display_drive(void); //显现数码管字模的驱动函数
  13. void display_service(void); //显现的窗口菜单服务程序
  14. //驱动LED的74HC595
  15. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
  16. void T0_time(void);//守时中止函数
  17. void key_service(void); //按键服务的应用程序
  18. void key_scan(void);//按键扫描函数 放在守时中止里
  19. void temper_control_service(void); //温控程序
  20. void ds18b20_sampling(void); //ds18b20采样程序
  21. void ds18b20_reset(); //复位ds18b20的时序
  22. unsigned char ds_read_byte(void ); //读一字节
  23. void ds_write_byte(unsigned char dat); //写一个字节
  24. unsigned int get_temper();//读取一次没有通过换算的温度数值
  25. sbit dq_dr_sr=P2^6; //ds18b20的数据驱动线
  26. sbit key_sr1=P0^0; //对应朱兆祺学习板的S1键
  27. sbit key_sr2=P0^1; //对应朱兆祺学习板的S5键
  28. sbit led_dr=P3^5;//LED灯,模仿工控中的继电器
  29. sbit key_gnd_dr=P0^4; //模仿独立按键的地GND,因而有必要一向输出低电平
  30. sbit beep_dr=P2^7; //蜂鸣器的驱动IO口
  31. sbit dig_hc595_sh_dr=P2^0; //数码管的74HC595程序
  32. sbit dig_hc595_st_dr=P2^1;
  33. sbit dig_hc595_ds_dr=P2^2;
  34. sbit hc595_sh_dr=P2^3; //LED灯的74HC595程序
  35. sbit hc595_st_dr=P2^4;
  36. sbit hc595_ds_dr=P2^5;
  37. unsigned int uiSampingCnt=0; //收集Ds1302的计时器,每秒钟更新收集一次
  38. unsigned char ucSignFlag=0; //正负符号。0代表正数,1代表负数,表明零下多少度。
  39. unsigned long ulCurrentTemper=33; //实践温度
  40. unsigned long ulSetTemper=26; //设定温度
  41. unsigned int uiTemperTemp=0; //中心变量
  42. unsigned char ucKeySec=0; //被触发的按键编号
  43. unsigned intuiKeyTimeCnt1=0; //按键去颤动延时计数器
  44. unsigned char ucKeyLock1=0; //按键触发后自锁的变量标志
  45. unsigned intuiKeyTimeCnt2=0; //按键去颤动延时计数器
  46. unsigned char ucKeyLock2=0; //按键触发后自锁的变量标志
  47. unsigned intuiVoiceCnt=0;//蜂鸣器鸣叫的持续时刻计数器
  48. unsigned charucVoiceLock=0;//蜂鸣器鸣叫的原子锁
  49. unsigned char ucDigShow8;//第8位数码管要显现的内容
  50. unsigned char ucDigShow7;//第7位数码管要显现的内容
  51. unsigned char ucDigShow6;//第6位数码管要显现的内容
  52. unsigned char ucDigShow5;//第5位数码管要显现的内容
  53. unsigned char ucDigShow4;//第4位数码管要显现的内容
  54. unsigned char ucDigShow3;//第3位数码管要显现的内容
  55. unsigned char ucDigShow2;//第2位数码管要显现的内容
  56. unsigned char ucDigShow1;//第1位数码管要显现的内容
  57. unsigned char ucDigDot8;//数码管8的小数点是否显现的标志
  58. unsigned char ucDigDot7;//数码管7的小数点是否显现的标志
  59. unsigned char ucDigDot6;//数码管6的小数点是否显现的标志
  60. unsigned char ucDigDot5;//数码管5的小数点是否显现的标志
  61. unsigned char ucDigDot4;//数码管4的小数点是否显现的标志
  62. unsigned char ucDigDot3;//数码管3的小数点是否显现的标志
  63. unsigned char ucDigDot2;//数码管2的小数点是否显现的标志
  64. unsigned char ucDigDot1;//数码管1的小数点是否显现的标志
  65. unsigned char ucDigShowTemp=0; //暂时中心变量
  66. unsigned char ucDisplayDriveStep=1;//动态扫描数码管的过程变量
  67. unsigned char ucWd=1;//因为本程序只要1个窗口,在实践项目中,此处的ucWd也能够省掉不要
  68. unsigned char ucWd1Part1Update=1;//在窗口1中,部分1的更新显现标志
  69. unsigned char ucWd1Part2Update=1; //在窗口1中,部分2的更新显现标志
  70. unsigned char ucTemp1=0;//中心过渡变量
  71. unsigned char ucTemp2=0;//中心过渡变量
  72. unsigned char ucTemp3=0;//中心过渡变量
  73. unsigned char ucTemp4=0;//中心过渡变量
  74. unsigned char ucTemp5=0;//中心过渡变量
  75. unsigned char ucTemp6=0;//中心过渡变量
  76. unsigned char ucTemp7=0;//中心过渡变量
  77. unsigned char ucTemp8=0;//中心过渡变量
  78. //依据原理图得出的共阴数码管字模表
  79. code unsigned char dig_table[]=
  80. {
  81. 0x3f,//0 序号0
  82. 0x06,//1 序号1
  83. 0x5b,//2 序号2
  84. 0x4f,//3 序号3
  85. 0x66,//4 序号4
  86. 0x6d,//5 序号5
  87. 0x7d,//6 序号6
  88. 0x07,//7 序号7
  89. 0x7f,//8 序号8
  90. 0x6f,//9 序号9
  91. 0x00,//无 序号10
  92. 0x40,//- 序号11
  93. 0x73,//P 序号12
  94. };
  95. void main()
  96. {
  97. initial_myself();
  98. delay_long(100);
  99. initial_peripheral();
  100. while(1)
  101. {
  102. key_service(); //按键服务的应用程序
  103. ds18b20_sampling(); //ds18b20采样程序
  104. temper_control_service(); //温控程序
  105. display_service(); //显现的窗口菜单服务程序
  106. }
  107. }
  108. /* 注释一:
  109. * 做温控设备的时分,为了防止继电器在临界温度邻近频频跳动切换,应该设置一个
  110. * 缓冲温差。本程序的缓冲温差是2度。
  111. */
  112. void temper_control_service(void) //温控程序
  113. {
  114. if(ucSignFlag==0) //是正数的前提下
  115. {
  116. if(ulCurrentTemper>=ulSetTemper)//当实践温度大于等于设定温度时
  117. {
  118. led_dr=0; //模仿继电器的LED灯平息
  119. }
  120. else if(ulCurrentTemper<=(ulSetTemper-2))//当实践温度小于等于设定温度2读以下时,这儿的2是缓冲温差2度
  121. {
  122. led_dr=1; //模仿继电器的LED灯点亮
  123. }
  124. }
  125. else//是负数,阐明是零下多少度的情况下
  126. {
  127. led_dr=1; //模仿继电器的LED灯点亮
  128. }
  129. }
  130. void ds18b20_sampling(void) //ds18b20采样程序
  131. {
  132. ++uiSampingCnt;//累计主循环次数的时刻
  133. if(uiSampingCnt>const_ds18b20_sampling_time)//每隔一段时刻就更新收集一次Ds18b20数据
  134. {
  135. uiSampingCnt=0;
  136. ET0=0;//制止守时中止
  137. uiTemperTemp=get_temper();//读取一次没有通过换算的温度数值
  138. ET0=1; //敞开守时中止
  139. if((uiTemperTemp&0xf800)==0xf800) //是负号
  140. {
  141. ucSignFlag=1;
  142. uiTemperTemp=~uiTemperTemp;//求补码
  143. uiTemperTemp=uiTemperTemp+1;
  144. }
  145. else //是正号
  146. {
  147. ucSignFlag=0;
  148. }
  149. ulCurrentTemper=0; //把int数据类型赋给long类型之前要先清零
  150. ulCurrentTemper=uiTemperTemp;
  151. ulCurrentTemper=ulCurrentTemper*10; //为了先保存一位小数点,所以扩大10倍,
  152. ulCurrentTemper=ulCurrentTemper>>4;//往右边移动4位,相当于乘以0.0625. 此刻保存了1位小数点,
  153. ulCurrentTemper=ulCurrentTemper+5;//四舍五入
  154. ulCurrentTemper=ulCurrentTemper/10; //四舍五入后,去掉小数点
  155. ucWd1Part2Update=1; //部分2更新显现实时温度
  156. }
  157. }
  158. //ds18b20驱动程序
  159. unsigned int get_temper()//读取一次没有通过换算的温度数值
  160. {
  161. unsigned char temper_H;
  162. unsigned char temper_L;
  163. unsigned int ds18b20_data=0;
  164. ds18b20_reset(); //复位ds18b20的时序
  165. ds_write_byte(0xCC);
  166. ds_write_byte(0x44);
  167. ds18b20_reset(); //复位ds18b20的时序
  168. ds_write_byte(0xCC);
  169. ds_write_byte(0xBE);
  170. temper_L=ds_read_byte();
  171. temper_H=ds_read_byte();
  172. ds18b20_data=temper_H; //把两个字节合并成一个int数据类型
  173. ds18b20_data=ds18b20_data<<8;
  174. ds18b20_data=ds18b20_data|temper_L;
  175. return ds18b20_data;
  176. }
  177. void ds18b20_reset() //复位ds18b20的时序
  178. {
  179. unsigned char x;
  180. dq_dr_sr=1;
  181. delay_short(8);
  182. dq_dr_sr=0;
  183. delay_short(80);
  184. dq_dr_sr=1;
  185. delay_short(14);
  186. x=dq_dr_sr;
  187. delay_short(20);
  188. }
  189. void ds_write_byte(unsigned char date) //写一个字节
  190. {
  191. unsigned chari;
  192. for(i=0;i<8;i++)
  193. {
  194. dq_dr_sr=0;
  195. dq_dr_sr=date&0x01;
  196. delay_short(5);
  197. dq_dr_sr=1;
  198. date=date>>1;
  199. }
  200. }
  201. unsigned char ds_read_byte(void ) //读一字节
  202. {
  203. unsigned char i;
  204. unsigned char date=0;
  205. for(i=0;i<8;i++)
  206. {
  207. dq_dr_sr=0;
  208. date=date>>1;
  209. dq_dr_sr=1;
  210. if(dq_dr_sr)
  211. {
  212. date=date|0x80;
  213. }
  214. delay_short(5);
  215. }
  216. return (date);
  217. }
  218. void display_service(void) //显现的窗口菜单服务程序
  219. {
  220. switch(ucWd)//因为本程序只要1个窗口,在实践项目中,此处的ucWd也能够省掉不要
  221. {
  222. case 1:
  223. if(ucWd1Part1Update==1)//部分设定温度更新显现
  224. {
  225. ucWd1Part1Update=0;
  226. ucTemp8=10; //显现空
  227. if(ulSetTemper>=100)
  228. {
  229. ucTemp7=ulSetTemper%1000/100; //显现设定温度的百位
  230. }
  231. else
  232. {
  233. ucTemp7=10; //显现空
  234. }
  235. if(ulSetTemper>=10)
  236. {
  237. ucTemp6=ulSetTemper%100/10; //显现设定温度的十位
  238. }
  239. else
  240. {
  241. ucTemp6=10; //显现空
  242. }
  243. ucTemp5=ulSetTemper%10; //显现设定温度的个位
  244. ucDigShow8=ucTemp8; //数码管显现实践内容
  245. ucDigShow7=ucTemp7;
  246. ucDigShow6=ucTemp6;
  247. ucDigShow5=ucTemp5;
  248. }
  249. if(ucWd1Part2Update==1)//部分实践温度更新显现
  250. {
  251. if(ucSignFlag==0)//正数
  252. {
  253. ucTemp4=10; //显现空
  254. }
  255. else//负数,阐明是零下多少度的情况下
  256. {
  257. ucTemp4=11; //显现负号-
  258. }
  259. if(ulCurrentTemper>=100)
  260. {
  261. ucTemp3=ulCurrentTemper%100/100; //显现实践温度的百位
  262. }
  263. else
  264. {
  265. ucTemp3=10; //显现空
  266. }
  267. if(ulCurrentTemper>=10)
  268. {
  269. ucTemp2=ulCurrentTemper%100/10;//显现实践温度的十位
  270. }
  271. else
  272. {
  273. ucTemp2=10;//显现空
  274. }
  275. ucTemp1=ulCurrentTemper%10; //显现实践温度的个数位
  276. ucDigShow4=ucTemp4; //数码管显现实践内容
  277. ucDigShow3=ucTemp3;
  278. ucDigShow2=ucTemp2;
  279. ucDigShow1=ucTemp1;
  280. }
  281. break;
  282. }
  283. }
  284. void key_scan(void)//按键扫描函数 放在守时中止里
  285. {
  286. if(key_sr1==1)//IO是高电平,阐明按键没有被按下,这时要及时清零一些标志位
  287. {
  288. ucKeyLock1=0; //按键自锁标志清零
  289. uiKeyTimeCnt1=0;//按键去颤动延时计数器清零,此行十分奇妙,是我实战中探索出来的。
  290. }
  291. else if(ucKeyLock1==0)//有按键按下,且是榜首次被按下
  292. {
  293. uiKeyTimeCnt1++; //累加守时中止次数
  294. if(uiKeyTimeCnt1>const_key_time1)
  295. {
  296. uiKeyTimeCnt1=0;
  297. ucKeyLock1=1;//自锁按键置位,防止一向触发
  298. ucKeySec=1; //触发1号键
  299. }
  300. }
  301. if(key_sr2==1)//IO是高电平,阐明按键没有被按下,这时要及时清零一些标志位
  302. {
  303. ucKeyLock2=0; //按键自锁标志清零
  304. uiKeyTimeCnt2=0;//按键去颤动延时计数器清零,此行十分奇妙,是我实战中探索出来的。
  305. }
  306. else if(ucKeyLock2==0)//有按键按下,且是榜首次被按下
  307. {
  308. uiKeyTimeCnt2++; //累加守时中止次数
  309. if(uiKeyTimeCnt2>const_key_time2)
  310. {
  311. uiKeyTimeCnt2=0;
  312. ucKeyLock2=1;//自锁按键置位,防止一向触发
  313. ucKeySec=2; //触发2号键
  314. }
  315. }
  316. }
  317. void key_service(void) //按键服务的应用程序
  318. {
  319. switch(ucKeySec) //按键服务状况切换
  320. {
  321. case 1:// 加按键 对应朱兆祺学习板的S1键
  322. switch(ucWd) //因为本程序只要1个窗口,在实践项目中,此处的ucWd也能够省掉不要
  323. {
  324. case 1: //在窗口1下设置设定温度
  325. ulSetTemper++;
  326. if(ulSetTemper>125)
  327. {
  328. ulSetTemper=125;
  329. }
  330. ucWd1Part1Update=1; //更新显现设定温度
  331. break;
  332. }
  333. ucVoiceLock=1;//原子锁加锁,维护主函数与中止函数的同享变量uiVoiceCnt
  334. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  335. ucVoiceLock=0;//原子锁解锁,维护主函数与中止函数的同享变量uiVoiceCnt
  336. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  337. break;
  338. case 2:// 减按键 对应朱兆祺学习板的S5键
  339. switch(ucWd) //因为本程序只要1个窗口,在实践项目中,此处的ucWd也能够省掉不要
  340. {
  341. case 1: //在窗口1下设置设定温度
  342. if(ulSetTemper>2)//因为缓冲温差是2度,所以我人为规则最小答应设定的温度不能低于2度
  343. {
  344. ulSetTemper–;
  345. }
  346. ucWd1Part1Update=1; //更新显现设定温度
  347. break;
  348. }
  349. ucVoiceLock=1;//原子锁加锁,维护主函数与中止函数的同享变量uiVoiceCnt
  350. uiVoiceCnt=const_voice_short; //按键声响触发,滴一声就停。
  351. ucVoiceLock=0;//原子锁解锁,维护主函数与中止函数的同享变量uiVoiceCnt
  352. ucKeySec=0;//呼应按键服务处理程序后,按键编号清零,防止共同触发
  353. break;
  354. }
  355. }
  356. void display_drive(void)
  357. {
  358. //以下程序,假如加一些数组和移位的元素,还能够紧缩容量。可是鸿哥寻求的不是容量,而是明晰的解说思路
  359. switch(ucDisplayDriveStep)
  360. {
  361. case 1://显现第1位
  362. ucDigShowTemp=dig_table[ucDigShow1];
  363. if(ucDigDot1==1)
  364. {
  365. ucDigShowTemp=ucDigShowTemp|0x80;//显现小数点
  366. }
  367. dig_hc595_drive(ucDigShowTemp,0xfe);
  368. break;
  369. case 2://显现第2位
  370. ucDigShowTemp=dig_table[ucDigShow2];
  371. if(ucDigDot2==1)
  372. {
  373. ucDigShowTemp=ucDigShowTemp|0x80;//显现小数点
  374. }
  375. dig_hc595_drive(ucDigShowTemp,0xfd);
  376. break;
  377. case 3://显现第3位
  378. ucDigShowTemp=dig_table[ucDigShow3];
  379. if(ucDigDot3==1)
  380. {
  381. ucDigShowTemp=ucDigShowTemp|0x80;//显现小数点
  382. }
  383. dig_hc595_drive(ucDigShowTemp,0xfb);
  384. break;
  385. case 4://显现第4位
  386. ucDigShowTemp=dig_table[ucDigShow4];
  387. if(ucDigDot4==1)
  388. {
  389. ucDigShowTemp=ucDigShowTemp|0x80;//显现小数点
  390. }
  391. dig_hc595_drive(ucDigShowTemp,0xf7);
  392. break;
  393. case 5://显现第5位
  394. ucDigShowTemp=dig_table[ucDigShow5];
  395. if(ucDigDot5==1)
  396. {
  397. ucDigShowTemp=ucDigShowTemp|0x80;//显现小数点
  398. }
  399. dig_hc595_drive(ucDigShowTemp,0xef);
  400. break;
  401. case 6://显现第6位
  402. ucDigShowTemp=dig_table[ucDigShow6];
  403. if(ucDigDot6==1)
  404. {
  405. ucDigShowTemp=ucDigShowTemp|0x80;//显现小数点
  406. }
  407. dig_hc595_drive(ucDigShowTemp,0xdf);
  408. break;
  409. case 7://显现第7位
  410. ucDigShowTemp=dig_table[ucDigShow7];
  411. if(ucDigDot7==1)
  412. {
  413. ucDigShowTemp=ucDigShowTemp|0x80;//显现小数点
  414. }
  415. dig_hc595_drive(ucDigShowTemp,0xbf);
  416. break;
  417. case 8://显现第8位
  418. ucDigShowTemp=dig_table[ucDigShow8];
  419. if(ucDigDot8==1)
  420. {
  421. ucDigShowTemp=ucDigShowTemp|0x80;//显现小数点
  422. }
  423. dig_hc595_drive(ucDigShowTemp,0x7f);
  424. break;
  425. }
  426. ucDisplayDriveStep++;
  427. if(ucDisplayDriveStep>8)//扫描完8个数码管后,从头从榜首个开端扫描
  428. {
  429. ucDisplayDriveStep=1;
  430. }
  431. }
  432. //数码管的74HC595驱动函数
  433. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01)
  434. {
  435. unsigned char i;
  436. unsigned char ucTempData;
  437. dig_hc595_sh_dr=0;
  438. dig_hc595_st_dr=0;
  439. ucTempData=ucDigStatusTemp16_09;//先送高8位
  440. for(i=0;i<8;i++)
  441. {
  442. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
  443. else dig_hc595_ds_dr=0;
  444. dig_hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  445. delay_short(1);
  446. dig_hc595_sh_dr=1;
  447. delay_short(1);
  448. ucTempData=ucTempData<<1;
  449. }
  450. ucTempData=ucDigStatusTemp08_01;//再先送低8位
  451. for(i=0;i<8;i++)
  452. {
  453. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
  454. else dig_hc595_ds_dr=0;
  455. dig_hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  456. delay_short(1);
  457. dig_hc595_sh_dr=1;
  458. delay_short(1);
  459. ucTempData=ucTempData<<1;
  460. }
  461. dig_hc595_st_dr=0;//ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上而且锁存起来
  462. delay_short(1);
  463. dig_hc595_st_dr=1;
  464. delay_short(1);
  465. dig_hc595_sh_dr=0; //拉低,抗搅扰就增强
  466. dig_hc595_st_dr=0;
  467. dig_hc595_ds_dr=0;
  468. }
  469. //LED灯的74HC595驱动函数
  470. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
  471. {
  472. unsigned char i;
  473. unsigned char ucTempData;
  474. hc595_sh_dr=0;
  475. hc595_st_dr=0;
  476. ucTempData=ucLedStatusTemp16_09;//先送高8位
  477. for(i=0;i<8;i++)
  478. {
  479. if(ucTempData>=0x80)hc595_ds_dr=1;
  480. else hc595_ds_dr=0;
  481. hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  482. delay_short(1);
  483. hc595_sh_dr=1;
  484. delay_short(1);
  485. ucTempData=ucTempData<<1;
  486. }
  487. ucTempData=ucLedStatusTemp08_01;//再先送低8位
  488. for(i=0;i<8;i++)
  489. {
  490. if(ucTempData>=0x80)hc595_ds_dr=1;
  491. else hc595_ds_dr=0;
  492. hc595_sh_dr=0; //SH引脚的上升沿把数据送入寄存器
  493. delay_short(1);
  494. hc595_sh_dr=1;
  495. delay_short(1);
  496. ucTempData=ucTempData<<1;
  497. }
  498. hc595_st_dr=0;//ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上而且锁存起来
  499. delay_short(1);
  500. hc595_st_dr=1;
  501. delay_short(1);
  502. hc595_sh_dr=0; //拉低,抗搅扰就增强
  503. hc595_st_dr=0;
  504. hc595_ds_dr=0;
  505. }
  506. void T0_time(void) interrupt 1 //守时中止
  507. {
  508. TF0=0;//铲除中止标志
  509. TR0=0; //关中止
  510. if(ucVoiceLock==0) //原子锁判别
  511. {
  512. if(uiVoiceCnt!=0)
  513. {
  514. uiVoiceCnt–; //每次进入守时中止都自减1,直到等于零中止。才中止鸣叫
  515. beep_dr=0;//蜂鸣器是PNP三极管操控,低电平就开端鸣叫。
  516. }
  517. else
  518. {
  519. ; //此处多加一个空指令,想保持跟if括号句子的数量对称,都是两条指令。不加也能够。
  520. beep_dr=1;//蜂鸣器是PNP三极管操控,高电平就中止鸣叫。
  521. }
  522. }
  523. key_scan(); //按键扫描函数
  524. display_drive();//数码管字模的驱动函数
  525. TH0=0xfe; //重装初始值(65535-500)=65035=0xfe0b
  526. TL0=0x0b;
  527. TR0=1;//开中止
  528. }
  529. void delay_short(unsigned int uiDelayShort)
  530. {
  531. unsigned int i;
  532. for(i=0;i
  533. {
  534. ; //一个分号相当于履行一条空句子
  535. }
  536. }
  537. void delay_long(unsigned int uiDelayLong)
  538. {
  539. unsigned int i;
  540. unsigned int j;
  541. for(i=0;i
  542. {
  543. for(j=0;j<500;j++)//内嵌循环的空指令数量
  544. {
  545. ; //一个分号相当于履行一条空句子
  546. }
  547. }
  548. }
  549. void initial_myself(void)//榜首区 初始化单片机
  550. {
  551. led_dr=0;//此处的LED灯模仿工控中的继电器
  552. key_gnd_dr=0; //模仿独立按键的地GND,因而有必要一向输出低电平
  553. beep_dr=1; //用PNP三极管操控蜂鸣器,输出高电平时不叫。
  554. hc595_drive(0x00,0x00);//封闭一切通过别的两个74HC595驱动的LED灯
  555. TMOD=0x01;//设置守时器0为工作方法1
  556. TH0=0xfe; //重装初始值(65535-500)=65035=0xfe0b
  557. TL0=0x0b;
  558. }
  559. void initial_peripheral(void) //第二区 初始化外围
  560. {
  561. ucDigDot8=0; //小数点悉数不显现
  562. ucDigDot7=0;
  563. ucDigDot6=0;
  564. ucDigDot5=0;
  565. ucDigDot4=0;
  566. ucDigDot3=0;
  567. ucDigDot2=0;
  568. ucDigDot1=0;
  569. EA=1; //开总中止
  570. ET0=1; //答应守时中止
  571. TR0=1; //发动守时中止
  572. }

总结陈词:
下一节开端讲单片机收集模仿信号的内容,欲知概况,请听下回分解—–使用ADC0832收集电压的模仿信号。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/ruanjian/262073.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部