圣源电子制作

 找回密码
 立即注册
查看: 8088|回复: 0

STC12C5406AD-NTC热敏电阻高精度温度计C程序

[复制链接]
发表于 2011-11-14 00:07:54 | 显示全部楼层 |阅读模式
转载自互联网!!!

STC12C5406AD 晶振频率为12MHz  

本程序已调试完成:

功能说明:采用廉价的NTC热敏电阻设计高精度温度计的方案,

根据NTC热敏电阻的温度特性,采用了较具新意程序算法;摆脱了传统的查表显示温度的方法,

特点:程序中无须查表,打破了常规的查表显示温度的方法。


  1. //NTC敏电阻温度显示。
  2. //DS18B20温度显示。


  3. #include "stc12c5410ad.h"//头文件
  4. #include "intrins.h"
  5. #define uchar unsigned char//宏定义
  6. #define uint unsigned int//宏定义

  7. sbit RS=P3^4;//定义I/O的硬件接口
  8. sbit E=P3^7;

  9. sbit A_B=P3^2;
  10. sbit CP=P3^3;

  11. sbit RT=P1^3;//外接NTC
  12. sbit R_100K=P1^4;//
  13. sbit D_J=P1^6;//检测

  14. sbit DQ=P1^5;////定义I/O的硬件接口--温度

  15. uint Temperature;//温度暂存单元
  16. uint Negative_Temperature;//负温度暂存单元
  17. bit Negative_sign=1;//负温度标志
  18. unsigned long TEMP_1;//长整形单元

  19. float Time_RT,Time_R;

  20. uchar aa,CC,ee;

  21. uint bb[11];

  22. float dd,temp5;

  23. uchar code DispTab_1[]={’0’,’1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’,’A’,’B’,’C’,’D’,’E’,’F’};//1602:0-9 数字
  24. uchar code DispTab_2[]={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};//温度符号
  25. uchar DispBuf[6]; //6字节的显示缓冲区

  26. void delay(uint z)//1ms延时
  27. {
  28. uchar x,x1;
  29. for(;z>0;z--)
  30. {
  31. for(x=0;x<114;x++)
  32. {
  33. for(x1=0;x1<1;x1++);
  34. }
  35. }
  36. }

  37. void delay1(uchar x2)//经精准计算,该段程序1次延时时间为 19.53us;多次调用需要重新计算。
  38. {
  39. while(x2>0)
  40. {
  41. x2--;
  42. }

  43. }

  44. void write_Directive(uchar a)//写指令
  45. {
  46. uchar i,temp;
  47. for(i=0;i<8;i++)
  48. {
  49. temp=a;
  50. temp&=0x80;
  51. if(temp==0x80)
  52. A_B=1;
  53. else
  54. A_B=0;
  55. a=a<<1;
  56. delay1(1);
  57. CP=0;
  58. delay1(1);
  59. CP=1;
  60. delay1(1);
  61. CP=0;
  62. }

  63. RS=0;
  64. delay(3);
  65. E=0;
  66. delay(3);
  67. E=1;
  68. delay(3);
  69. E=0;
  70. delay(3);
  71. }

  72. void write_Data(uchar a)//写数据
  73. {
  74. uchar i,temp;
  75. for(i=0;i<8;i++)
  76. {
  77. temp=a;
  78. temp&=0x80;
  79. if(temp==0x80)
  80. A_B=1;
  81. else
  82. A_B=0;
  83. a=a<<1;
  84. delay1(1);
  85. CP=0;
  86. delay1(1);
  87. CP=1;
  88. delay1(1);
  89. }

  90. RS=1;
  91. delay(3);
  92. E=0;
  93. delay(3);
  94. E=1;
  95. delay(3);
  96. E=0;
  97. delay(3);

  98. }

  99. void init()//初始化
  100. {

  101. TMOD=0x10;//定时器T1工作于方式1,16位计数器

  102. TH1=0x00;
  103. TL1=0x00;

  104. EA=1;//开总中断允许
  105. ET1=1;//开定时器T1允许控制
  106. //PT1=1;//开定时器T1中断为最高优先级
  107. TR1=0;//T1开始运行

  108. P1M1=0x80;
  109. P1M0=0x80;

  110. //aa=TH1;
  111. //aa=aa<<8;
  112. //aa|=TL1;

  113. //Time_RT=aa;

  114. //Time_RT=Time_RT|TL1;

  115. _nop_();

  116. delay(15);
  117. write_Directive(0x38);
  118. delay(5);
  119. write_Directive(0x38);
  120. delay(5);
  121. write_Directive(0x38);
  122. write_Directive(0x01);
  123. write_Directive(0x02);///初始化后数据地址为0x80;即第一行,第一个位置
  124. write_Directive(0x0c);
  125. }

  126. void Temperature_symbol()//温度符号
  127. {
  128. uchar i;
  129. for(i=0;i<8;i++)
  130. {
  131. write_Directive(0x40+i);//写入温度符号
  132. write_Data(DispTab_2[i]);
  133. }
  134. }

  135. void write_Data_String()//显示时间函数
  136. {
  137. uchar i;
  138. uint mm,mb;
  139. mb=temp5;
  140. // DispBuf[0]=temp/10000;//显示百位
  141. // mm=temp%10000;

  142. // DispBuf[1]=mm/1000;//显示十位
  143. // mm=mm%1000;

  144. // DispBuf[2]=mm/100;//显示个位
  145. // mm=mm%100;

  146. DispBuf[1]=mb/100;//显示小数点:0.001
  147. mm=mb%100;//显示小数点:0.0001

  148. DispBuf[2]=mm/10;//显示小数点:0.001
  149. DispBuf[3]=mm%10;//显示小数点:0.0001

  150. //i=DispBuf[0];//百位判断,如果为0,则消隐
  151. //if(i==0)
  152. // i=10;

  153. //DispBuf[0]=DispTab_1[i];//查表,取字符
  154. i=DispBuf[1];
  155. DispBuf[1]=DispTab_1[i];
  156. i=DispBuf[2];
  157. DispBuf[2]=DispTab_1[i];
  158. i=DispBuf[3];
  159. DispBuf[3]=DispTab_1[i];
  160. //i=DispBuf[4];
  161. //DispBuf[4]=DispTab_1[i];

  162. write_Directive(0x80+0x00);//第一行,第五个位置地址
  163. write_Data(’N’);
  164. write_Data(’T’);
  165. write_Data(’C’);
  166. //write_Data(’5’);
  167. //write_Data(’D’);
  168. //write_Data(’Z’);
  169. //write_Data(’ ’);
  170. write_Data(’:’);

  171. //write_Data(DispBuf[0]);//第一行,第五个位置


  172. write_Data(DispBuf[1]);//第一行,第七个位置


  173. write_Data(DispBuf[2]);//第一行,第八个位置

  174. write_Data(’.’);//第一行,第六个位置

  175. write_Data(DispBuf[3]);//第一行,第九个位置

  176. //write_Data(DispBuf[4]);//第一行,第十个位置

  177. //write_Data(0x00);//第一行,第十三个位置显示温度符号

  178. }

  179. void DB18B20_init()//DB18B20复位
  180. {
  181. DQ=1;
  182. delay1(1);//程序1次延时时间为 19.53us
  183. DQ=0;
  184. delay1(250);//程序110次延时时间为 965.71us
  185. DQ=1;
  186. delay1(10);//程序1次延时时间为 19.53us
  187. while(DQ==1);
  188. //if(DQ==0)
  189. _nop_();
  190. // LED_7=~led_7;//led检测复位正常否,如果DB18B20存在,且正常;led闪烁。
  191. while(DQ==0);
  192. delay1(40);//程序20次延时时间为 197.32us

  193. }

  194. void write_DB18B20(uchar m1)//写DB18B20
  195. {
  196. uchar i,m2;

  197. for(i=0;i<8;i++)
  198. {
  199. m2=m1;
  200. m2=m2&0x01;
  201. DQ=0;
  202. _nop_();
  203. DQ=1;
  204. if(m2==0x01)
  205. DQ=1;
  206. else
  207. DQ=0;
  208. delay1(50);//程序5次延时时间为 54.25us
  209. m1=m1>>1;
  210. DQ=1;

  211. }
  212. }

  213. read_DB18B20()//读DB18B20
  214. {
  215. uint temp_1;
  216. uchar i;
  217. for(i=0;i<16;i++)
  218. {
  219. temp_1=temp_1>>1;
  220. DQ=1;
  221. _nop_();
  222. DQ=0;
  223. _nop_();
  224. DQ=1;
  225. _nop_();
  226. _nop_();
  227. _nop_();
  228. _nop_();
  229. if(DQ==1)
  230. temp_1=temp_1|0x8000;
  231. //else
  232. // temp_1=temp_1|0x0000;
  233. delay1(50);//程序5次延时时间为 54.25us
  234. }
  235. return temp_1;//返回温度值
  236. }

  237. void Negative()//温度为零度以下时,将变换温度
  238. {
  239. Negative_Temperature=Temperature;
  240. Negative_Temperature=Negative_Temperature&0xf800;
  241. if(Negative_Temperature==0xf800)
  242. {
  243. Temperature=~Temperature;
  244. Temperature=Temperature+1;
  245. Negative_sign=0;
  246. }
  247. }

  248. void write_Data_String1()//显示时间函数
  249. {
  250. uchar i;
  251. unsigned long mm;
  252. DispBuf[0]=TEMP_1/1000000;//显示百位
  253. mm=TEMP_1%1000000;

  254. DispBuf[1]=mm/100000;//显示十位
  255. mm=mm%100000;

  256. DispBuf[2]=mm/10000;//显示个位
  257. mm=mm%10000;

  258. DispBuf[3]=mm/1000;//显示小数点:0.1
  259. mm=mm%1000;

  260. DispBuf[4]=mm/100;//显示小数点:0.01
  261. mm=mm%100;

  262. DispBuf[5]=mm/10;//显示小数点:0.001
  263. DispBuf[6]=mm%10;//显示小数点:0.0001

  264. i=DispBuf[0];//百位判断,如果为0,则消隐
  265. if(i==0)
  266. i=10;
  267. else if(Negative_sign==0)//负温度判断,如果为0,则温度为负的,显示负号
  268. i=11;

  269. DispBuf[0]=DispTab_1[i];//查表,取字符
  270. i=DispBuf[1];
  271. DispBuf[1]=DispTab_1[i];
  272. i=DispBuf[2];
  273. DispBuf[2]=DispTab_1[i];
  274. i=DispBuf[3];
  275. DispBuf[3]=DispTab_1[i];
  276. i=DispBuf[4];
  277. DispBuf[4]=DispTab_1[i];
  278. i=DispBuf[5];
  279. DispBuf[5]=DispTab_1[i];
  280. i=DispBuf[6];
  281. DispBuf[6]=DispTab_1[i];


  282. write_Directive(0x80+0x40);//第一行,第五个位置地址

  283. write_Data(’D’);
  284. write_Data(’S’);
  285. write_Data(’1’);
  286. write_Data(’8’);
  287. write_Data(’B’);
  288. write_Data(’2’);
  289. write_Data(’0’);
  290. write_Data(’:’);
  291. //write_Data(DispBuf[0]);//第一行,第五个位置
  292. //
  293. write_Data(DispBuf[1]);//第一行,第六个位置
  294. write_Data(DispBuf[2]);//第一行,第八个位置

  295. write_Data(’.’);//第一行,第七个位置

  296. write_Data(DispBuf[3]);//第一行,第九个位置

  297. write_Data(DispBuf[4]);//第一行,第十个位置

  298. //write_Data(DispBuf[5]);//第一行,第十一个位置
  299. //write_Data(DispBuf[6]);//第一行,第十二个位置
  300. write_Data(0x00);//第一行,第十三个位置显示温度符号

  301. }

  302. void Timer1() interrupt 3//TR1
  303. {
  304. //TR1=0;
  305. }
  306. //P1M0=0x08;//P1.3高阻
  307. /*
  308. void RT_DJ()
  309. {
  310. D_J=0;
  311. R_100K=0;
  312. P1M0=0x18;//P1.3,P1.4高阻
  313. P1M1=0x18;//P1.3,P1.4高阻

  314. TH1=0x00;
  315. TL1=0x00;
  316. P1M0=0x48;//P1.3,P1.6高阻
  317. P1M1=0x48;//P1.3,P1.6高阻

  318. R_100K=1;
  319. TR1=1;
  320. while(!D_J);
  321. TR1=0;
  322. aa=TH1;
  323. aa=aa<<8;
  324. aa|=TL1;
  325. Time_R=aa;
  326. temp=aa;

  327. }*/

  328. void ADC_Conversion()//ADC开始转
  329. {
  330. ADC_CONTR=0x87;
  331. delay(1);
  332. ADC_CONTR=0x8f;
  333. delay(1);
  334. //while((ADC_CONTR==0x8f));
  335. ADC_CONTR=0x87;
  336. delay(1);
  337. //temp=ADC_DATA;//高8位
  338. }

  339. void main()
  340. {

  341. //delay1(5);//程序1次延时时间为 19.53us
  342. //P1M1=0x80;
  343. //P1M0=0x80;
  344. ///sbit RT=P1^3;//外接NTC
  345. //sbit R_100K=P1^4;//
  346. //sbit D_J=P1^6;//检测
  347. uchar i;
  348. cc=0x3d;
  349. dd=30;
  350. //goto lk;
  351. init();

  352. Temperature_symbol();//写入温度符号
  353. while(1)
  354. {

  355. DB18B20_init();//DB18B20复位

  356. write_DB18B20(0xcc);//写DB18B20;0xcc 跳过 ROM 指令
  357. write_DB18B20(0x44);//写DB18B20;0x44 启动温度转换指令

  358. delay(1000);//延时1秒

  359. DB18B20_init();//DB18B20复位
  360. write_DB18B20(0xcc);//写DB18B20;0xcc 跳过 ROM 指令
  361. write_DB18B20(0xbe);//写DB18B20;0xbe 读温度指令
  362. Temperature=read_DB18B20();//读 DB18B20 温度,读出的温度在 Temperature
  363. Negative();//温度为零度以下时,将变换温度,否则不变
  364. TEMP_1=Temperature*0.0625*10000;//转换成 十进制(*10000,表示,显示到小数点后4位:0.0000)
  365. write_Data_String1();//显示温度


  366. //RT_DJ();
  367. for(i=0;i<10;i++)
  368. {
  369. ADC_Conversion();
  370. bb[i]=ADC_DATA;//高8位;

  371. }
  372. Time_RT=bb[0]+bb[1]+bb[2]+bb[3]+bb[4]+bb[5]+bb[6]+bb[7]+bb[8]+bb[9];
  373. ee=Time_RT/10;
  374. //lk: temp=0x46;
  375. //if(ee==cc)
  376. //{
  377. // temp5=30;
  378. //}
  379. if(ee>cc)
  380. {
  381. for(i=0;i<94;i++)
  382. {
  383. cc=cc+1;
  384. dd=dd+0.5;
  385. if(ee==cc)
  386. {
  387. temp5=dd*10;
  388. i=93;
  389. }
  390. }
  391. }
  392. if(ee<cc)
  393. {
  394. for(i=0;i<30;i++)
  395. {
  396. cc=cc-1;
  397. dd=dd-0.5;
  398. if(ee==cc)
  399. {
  400. temp5=dd*10;
  401. i=29;
  402. }
  403. }
  404. }
  405. write_Data_String();
  406. delay(100);
  407. }
  408. }
复制代码




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|联系我们|闽公网安备 35012102000020号|圣源电子 ( 闽ICP备11020110号 )

GMT+8, 2024-3-29 22:25 , Processed in 0.049422 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表