找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 4572|回復(fù): 2
打印 上一主題 下一主題
收起左側(cè)

ACS712+51單片機(jī)電流測(cè)量程序與Proteus仿真圖

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
acs712+51單片機(jī)+DS18B20溫度與電流測(cè)量電路與程序
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機(jī)源程序如下:
  1. #include<reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit DQ=P0^1; //ds18b20 與單片機(jī)連接口

  5. sbit RS=P1^0; //1602 寫(xiě)數(shù)據(jù) / 寫(xiě)命令選擇端口
  6. //RS=1 寫(xiě)數(shù)據(jù),即要顯示的內(nèi)容
  7. //RS=0 寫(xiě)命令,即一些 LCD設(shè)置命令
  8. sbit RW=P1^1; //1602 讀/ 寫(xiě)選擇端, RW=0為寫(xiě)模式
  9. sbit EN=P1^2; // 給 EN一個(gè)高脈沖,將數(shù)據(jù)送入液晶控制器,完成寫(xiě)操作

  10. /******adc配置*****/
  11. sbit EOC_1543 = P3 ^ 7;
  12. sbit SCLK_1543 = P3 ^ 5;
  13. sbit ADDR_1543 = P3 ^ 3;
  14. sbit DOUT_1543 = P3 ^ 2;
  15. sbit CS_1543 = P3 ^ 4;

  16. uchar code str1[]={"cur:"};
  17. uchar code str2[]={"temp:"};
  18. uchar data disdata[4];// 百、十、個(gè)、小數(shù)位
  19. uchar data cur_c[3];

  20. uint tvalue; // 溫度值
  21. uchar tflag; // 溫度正負(fù)標(biāo)志
  22. /**********************lcd1602 設(shè)置子函數(shù) *********************/
  23. void delay1ms(uint ms) // 延時(shí) 1 毫秒子函數(shù) ,形參為 ms(不夠精確的)
  24. {
  25. unsigned int i,j;
  26. for(i=0;i<ms;i++)
  27. for(j=0;j<120;j++);
  28. }

  29. void delayus(unsigned char x)   // 延時(shí) (x*2+5) us
  30. {
  31.     while(--x);
  32. }
  33. void wr_com(uchar com) //lcd 寫(xiě)控制指令子函數(shù),形參為 com
  34. {
  35. delay1ms(1); // 調(diào)用延時(shí)子函數(shù),并用實(shí)參 1 代替延時(shí)子函數(shù)中的形參 ms
  36. RS=0; //RS=0 進(jìn)入寫(xiě)命令狀態(tài),即一些 LCD設(shè)置命令
  37. RW=0; //RW=0 為寫(xiě)模式
  38. EN=0;  //EN=0 時(shí)不能完成寫(xiě)操作
  39. P2=com; // 把要設(shè)置的指令碼 com送給 P2 口
  40. delay1ms(1);
  41. EN=1; // 給 EN一個(gè)高脈沖,將數(shù)據(jù)送入液晶控制器,完成寫(xiě)操作
  42. delay1ms(1);
  43. EN=0; }//EN=0 時(shí)不能完成寫(xiě)操作
  44. /******************檢測(cè)忙標(biāo)志函數(shù)***************************/  
  45. void check_busy(void)
  46. {
  47.   uchar dt;
  48.   do
  49. {
  50.               dt=0xff;
  51.               EN=0;
  52.               RS=0;
  53.               RW=1;
  54.               EN=1;
  55.               dt=P2;
  56.               }while(dt&0x80);
  57.               EN=0;
  58. }

  59. //*****************寫(xiě)數(shù)據(jù)*******************************/
  60. void wr_dat(uchar dat) //lcd 寫(xiě)顯示數(shù)據(jù)子函數(shù),形參為 dat
  61. {
  62. /* check_busy();*/
  63. delay1ms(1);
  64. RS=1; //RS=1 進(jìn)入寫(xiě)數(shù)據(jù)狀態(tài),即要顯示的內(nèi)容
  65. RW=0; //RW=0 為寫(xiě)模式
  66. EN=0; //EN=0 時(shí)不能完成寫(xiě)操作
  67. P2=dat; // 把要顯示的數(shù)據(jù) dat 送給 P2 口
  68. delay1ms(1);
  69. EN=1; // 給 EN一個(gè)高脈沖,將數(shù)據(jù)送入液晶控制器,完成寫(xiě)操作
  70. delay1ms(1);
  71. EN=0; //EN=0 時(shí)不能完成寫(xiě)操作
  72. }
  73. void lcd_init() //lcd 初始化設(shè)置子函數(shù),不帶參數(shù) ,0x38 是顯示模式設(shè)置 , 其余是顯示開(kāi) / 關(guān)及光標(biāo)設(shè)置,無(wú)順序
  74. {
  75. delay1ms(15);
  76. wr_com(0x38); // 調(diào)用寫(xiě)控制指令子函數(shù),并用實(shí)參 "0011 1000" 代替形參 com
  77. //0x38 表示設(shè)置為 16*2 顯示,每個(gè)塊為 5*7 點(diǎn)陣, 8 位數(shù)據(jù)接口
  78. delay1ms(5);
  79. wr_com(0x08); // 調(diào)用寫(xiě)控制指令子函數(shù),并用實(shí)參 "0000 1000" 代替形參 com
  80. //0x08 表示設(shè)置為關(guān)顯示、不顯示光標(biāo)、光標(biāo)不閃爍
  81. delay1ms(5);
  82. wr_com(0x01); // 調(diào)用寫(xiě)控制指令子函數(shù),并用實(shí)參 "0000 0001" 代替形參 com
  83. //0x01 表示顯示數(shù)據(jù)清屏(數(shù)據(jù)指針清 0,所有顯示清 0)
  84. delay1ms(5);
  85. wr_com(0x06);// 調(diào)用寫(xiě)控制指令子函數(shù),并用實(shí)參 "0000 0110" 代替形參 com
  86. //0x06 表示當(dāng)讀或?qū)懸粋(gè)字符后地址指針加 1,且光標(biāo)加 1; 當(dāng)寫(xiě)一個(gè)字符時(shí),整屏顯示不移動(dòng)
  87. delay1ms(5);
  88. wr_com(0x0c);// 調(diào)用寫(xiě)控制指令子函數(shù),并用實(shí)參 "0000 1100" 代替形參 com
  89. //0x0c 打開(kāi)顯示、不顯示光標(biāo)、光標(biāo)不閃爍
  90. delay1ms(5);
  91. }
  92. void display(uchar *p) //lcd 顯示字符串子函數(shù)
  93. {
  94. while(*p!='\0') // 測(cè)試是否等于 '\0' ,即判斷字符是否結(jié)尾
  95. {
  96. wr_dat(*p); // 顯示指針?biāo)傅淖址?br />
  97. p++; // 指針加 1
  98. delay1ms(1);
  99. }
  100. }
  101. void init_play() // 初始化顯示子函數(shù)
  102. {
  103. lcd_init(); // 調(diào)用 lcd 初始化設(shè)置子函數(shù),對(duì) LCD進(jìn)行初始化
  104. wr_com(0x80); // 調(diào)用寫(xiě)控制指令子函數(shù),并用實(shí)參 "1000 0000" 代替形參 com
  105. // 并將數(shù)據(jù)指針定位到第一行第一個(gè)字符處
  106. display(str1);// 從第一行第一個(gè)字符處顯示字符串 str1
  107. wr_com(0x80+0x40);// 調(diào)用寫(xiě)控制指令子函數(shù),并用實(shí)參 "1000 0000" 代替形參 com
  108. // 并將數(shù)據(jù)指針定位到第二行第一個(gè)字符處
  109. display(str2); // 從第二行第一個(gè)字符處顯示字符串 str2
  110. }

  111. /********************************************************/
  112. /********************ds18b20 程序 ***********************/
  113. void delay_18b20(uint i) // 延時(shí) 1 微秒
  114. {
  115. while(i--);
  116. }
  117. void ds18b20rst() //ds18b20 初始化子函數(shù)
  118. // 要求"數(shù)據(jù)線拉高 - 延時(shí) - 數(shù)據(jù)線拉低 - 延時(shí)大于 480 微妙 -數(shù)據(jù)線拉高 - 延時(shí)等待 "
  119. {
  120. uchar x=0;
  121. DQ = 1; // 信號(hào)線 DQ復(fù)位
  122. delay_18b20(4); // 延時(shí)
  123. DQ = 0; //DQ 拉低
  124. delay_18b20(100); // 精確延時(shí)大于 480us
  125. DQ = 1; // 拉高
  126. delay_18b20(40);
  127. }
  128. void ds18b20wr(uchar wdata) /* 寫(xiě)數(shù)據(jù)子函數(shù) , 無(wú)返回值,含參數(shù) */
  129. {
  130. uchar i=0;
  131. for (i=8; i>0; i--)// 要寫(xiě)完一個(gè)字節(jié),故需要重復(fù) 8 次以下操作
  132. {
  133. DQ = 0; // 數(shù)據(jù)線拉低
  134. DQ = wdata&0x01;//wdata 是一個(gè)形參,將其與 0000 0001 進(jìn)行按位與
  135. // 按從低到高的順序發(fā)送數(shù)據(jù)(一次發(fā)送一位 )
  136. delay_18b20(10);
  137. DQ = 1; // 最后將數(shù)據(jù)線拉高
  138. wdata>>=1; // 將 wdata 右移 1 位
  139. }
  140. }
  141. uchar ds18b20rd() // 讀數(shù)據(jù)子函數(shù) , 是有返回值 dat
  142. {
  143. uchar i=0;
  144. uchar dat = 0;
  145. for (i=8;i>0;i--)// 要讀完一個(gè)字節(jié),故需要重復(fù) 8 次以下操作
  146. {
  147. DQ = 0; // 給脈沖信號(hào)
  148. dat>>=1;
  149. DQ = 1; // 給脈沖信號(hào)
  150. if(DQ)
  151. dat|=0x80;
  152. delay_18b20(10);
  153. }
  154. return(dat); // 返回 dat
  155. }
  156. read_temp() // 讀取溫度值并轉(zhuǎn)換的子函數(shù),有返回值溫度值 tvalue
  157. {
  158. uchar a,b;
  159. ds18b20rst(); // 調(diào)用 ds18b20 初始化子函數(shù)
  160. ds18b20wr(0xcc);// 調(diào)用寫(xiě)數(shù)據(jù)子函數(shù),向 ds18b20 寫(xiě)命令 0xcc
  161. //ccH 表示跳過(guò) ROM讀序列號(hào),適用于單機(jī)工作,直接向 18b20 發(fā)送溫度變換命令
  162. ds18b20wr(0x44);// 調(diào)用寫(xiě)數(shù)據(jù)子函數(shù),向 ds18b20 寫(xiě)命令 0x44
  163. //44H 表示啟動(dòng) ds18b20 溫度轉(zhuǎn)換 , 結(jié)果自行存入 9 字節(jié)的 RAM中
  164. ds18b20rst(); // 調(diào)用 ds18b20 初始化子函數(shù)
  165. ds18b20wr(0xcc);// 同上
  166. ds18b20wr(0xbe);// 調(diào)用寫(xiě)數(shù)據(jù)子函數(shù),向 ds18b20 寫(xiě)命令 0xbe
  167. //beH 表示讀取 RAM中 9 字節(jié)的溫度數(shù)據(jù)
  168. a=ds18b20rd(); // 調(diào)用讀數(shù)據(jù)子函數(shù),并將所得數(shù)據(jù)給 a
  169. b=ds18b20rd(); //
  170. tvalue=b; // 把 b 的值給 tvalue
  171. tvalue<<=8; //tvalue 左移 8 位
  172. tvalue=tvalue|a;//tvalue 與 a 進(jìn)行按位或
  173. if(tvalue<0x0fff)//
  174. tflag=0; // 前五位為 0 時(shí),讀取的溫度為正,標(biāo)志位為 0,此時(shí)只要
  175. // 將測(cè)得數(shù)值乘以 0.0625 即可得到實(shí)際溫度
  176. else // 前五位為 1 時(shí),讀取的溫度為負(fù),標(biāo)志位為 1,此時(shí)需要
  177. { // 將測(cè)得數(shù)值取反后再加 1,再乘以 0.0625 即可得到實(shí)際溫度
  178. tflag=1; // 此時(shí)表示負(fù)溫度
  179. tvalue=~tvalue+1;
  180. }
  181. tvalue=tvalue*(0.625);// 溫度值擴(kuò)大 10 倍,精確到 1 位小數(shù)
  182. return(tvalue); // 返回溫度值
  183. }
  184. /**********************************************************/
  185. /************************ 溫度值顯示 *********************/
  186. void ds18b20disp() // 溫度值顯示
  187. {
  188. uchar flagdat;
  189. disdata[0]=tvalue/1000+0x30; // 百位數(shù)
  190. disdata[1]=tvalue%1000/100+0x30;// 十位數(shù)
  191. disdata[2]=tvalue%100/10+0x30; // 個(gè)位數(shù)
  192. disdata[3]=tvalue%10+0x30; // 小數(shù)位
  193. if(tflag==0)
  194. flagdat=0x2b; // 正溫度顯示符號(hào) :+
  195. else
  196. flagdat=0x2d; // 負(fù)溫度顯示負(fù)號(hào) :-
  197. if(disdata[0]==0x30)
  198. {
  199. disdata[0]=0x20; // 如果百位為 0,不顯示
  200. if(disdata[1]==0x30)
  201. {
  202. disdata[1]=0x20; // 如果百位為 0,十位為 0 也不顯示
  203. }
  204. }
  205. wr_com(0x80+0x46); // 定位數(shù)據(jù)指針的位置:第二行第五個(gè)字符處
  206. wr_dat(flagdat); // 顯示符號(hào)位
  207. wr_com(0x80+0x47);  // 定位數(shù)據(jù)指針的位置:第二行第六個(gè)字符處
  208. wr_dat(disdata[0]);  // 顯示百位
  209. wr_com(0x80+0x48);  // 定位數(shù)據(jù)指針的位置:第二行第七個(gè)字符處
  210. wr_dat(disdata[1]);  // 顯示十位
  211. wr_com(0x80+0x49);  // 定位數(shù)據(jù)指針的位置:第二行第八個(gè)字符處
  212. wr_dat(disdata[2]);  // 顯示個(gè)位
  213. wr_com(0x80+0x4A);  // 定位數(shù)據(jù)指針的位置:第二行第九個(gè)字符處
  214. wr_dat(0x2e); // 顯示小數(shù)點(diǎn)
  215. wr_com(0x80+0x4B);  // 定位數(shù)據(jù)指針的位置:第二行第十個(gè)字符處
  216. wr_dat(disdata[3]);  // 顯示小數(shù)位
  217.               /**********************顯示攝氏度************************/
  218. wr_com(0x80+0x4C);  // 定位數(shù)據(jù)指針的位置:第二行第十一個(gè)字符處
  219. wr_dat(0XDF);
  220. wr_com(0x80+0x4D);  // 定位數(shù)據(jù)指針的位置:第二行第十二個(gè)字符處
  221. wr_dat(0X43);
  222. }

  223. /**********************************************************/
  224. /********************TLC1543************************/
  225. void TLC1543_init(void)
  226. {
  227.         CS_1543 = 1;
  228.         SCLK_1543 = 0;
  229. }


  230. uint ReadADC_TLC1543(uchar ain)
  231. {
  232.         uchar t;
  233.         uint adc_value = 0;
  234.         ain <<= 4;

  235.         CS_1543 = 0;
  236.         for (t = 0; t < 10; t++)         // 將判斷語(yǔ)句改為 temp<12
  237.         {                                       // 程序可移殖至 TLC2543.
  238.                 adc_value <<= 1;
  239.                 ain <<= 1;
  240.                 ADDR_1543 = CY;
  241.                 if (DOUT_1543)   adc_value += 1;
  242.                 SCLK_1543 = 1;
  243.                 delayus(1);
  244.                 SCLK_1543 = 0;
  245.         }
  246.         CS_1543 = 1;

  247.         return  adc_value;
  248. }

  249. uint get_cur()
  250. {
  251.         uint vol,cur_1;
  252.         vol = ReadADC_TLC1543(0) * 0.49; //輸入adc電壓的100倍。4.9=5(參照電壓)*/1024(10位)*100(用于顯示)
  253.         cur_1 = 5*vol-1250; //實(shí)際電流的100倍用于顯示,cur_real=(vol_real-2.5)*5
  254.         return cur_1;
  255. }

  256. void displaycur(uint cur)
  257. {
  258.         cur_c[0] = cur/1000%10+0x30;
  259.         cur_c[1]= cur/100%100+0x30;
  260.     cur_c[2]= cur/10%10+0x30;
  261.         wr_com(0x80 + 0x07);  // 定位數(shù)據(jù)指針的位置:第一行第七個(gè)字符處
  262.         wr_dat(cur_c[0]);  // 顯示十位
  263.         wr_com(0x80 + 0x08);  // 定位數(shù)據(jù)指針的位置:第一行第八個(gè)字符處
  264.         wr_dat(cur_c[1]);  // 顯示個(gè)位
  265.         wr_com(0x80 + 0x09);  // 定位數(shù)據(jù)指針的位置:第一行第九個(gè)字符處
  266.         wr_dat(0x2e); // 顯示小數(shù)點(diǎn)
  267.         wr_com(0x80 + 0x0A);  // 定位數(shù)據(jù)指針的位置:第一行第十個(gè)字符處
  268.         wr_dat(cur_c[2]);  // 顯示小數(shù)位
  269.         wr_com(0x80 + 0x0C);  // 定位數(shù)據(jù)指針的位置:第二行第十二個(gè)字符處
  270.         wr_dat(0X41);
  271. }

  272. /*******************************************************/
  273. /******************** 主程序 *****************************/
  274. void main()
  275. {
  276. init_play();  // 調(diào)用 lcd 初始化顯示子函數(shù)
  277. TLC1543_init();
  278. while(1)
  279. {
  280. read_temp(); // 調(diào)用 ds18b20 讀取溫度
  281. ds18b20disp(); // 調(diào)用溫度顯示子函數(shù)
  282. displaycur(get_cur());
  283. }
  284. }
復(fù)制代碼
Keil5代碼與Proteus8.8仿真下載:
51單片機(jī)電流測(cè)量.zip (92.19 KB, 下載次數(shù): 143)

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏5 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:1004160 發(fā)表于 2023-10-2 20:43 | 只看該作者
樓主,我測(cè)試交流電流,換了個(gè)激勵(lì)源(就是一個(gè)圈圈的那種220V的),是測(cè)不到正確電流的。但是換了一個(gè)探針類(lèi)型的就可以了,這是為什么?

1.png (15.22 KB, 下載次數(shù): 69)

1.png
回復(fù)

使用道具 舉報(bào)

板凳
ID:1122276 發(fā)表于 2024-8-2 19:49 | 只看該作者
xinwuhen 發(fā)表于 2023-10-2 20:43
樓主,我測(cè)試交流電流,換了個(gè)激勵(lì)源(就是一個(gè)圈圈的那種220V的),是測(cè)不到正確電流的。但是換了一個(gè)探針類(lèi) ...

你試過(guò)用測(cè)直流嗎
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表