久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1926|回復: 0
打印 上一主題 下一主題
收起左側

51單片機實現紅外探頭ADC數值讀取程序 實現紅外巡線

[復制鏈接]
跳轉到指定樓層
樓主
使用單片機型號STC15W408AS-35I-DIP20,焊接效果如附件圖。使用程序可以讀取所有紅外探頭的ADC數值,可以進行IIC通信。
這種單片機一次具有8個ADC,一個芯片就能實現8個探頭的數據轉換。

這樣的設計可以實現紅外巡線等功能。



# 紅外巡線測試結果

2022年8月23日23:10:10

## 裝車效果

只裝了一塊彎的,效果很好。

探頭頂端距離地面大約8mm(目測)。

## 我的程序

### 從機

從機傳輸數據的時候LED亮起。

6個探頭的從機傳回的數據:\[data*6] \[0] \[addr]

8個探頭的從機傳回的數據:\[data*8]

### 主機

主機使用STM32F401CCU6,配置IIC2引腳,波特率為一個非標準的傳輸波特率(10000,標準值為100k(標準IIC)或400k(高速IIC))。

主機對所有地址的從機進行檢測,對每個從機,會循環嘗試傳輸,直到傳輸成功或傳輸次數達到5次為止。

把所有從機地址檢測完畢之后重新開始。

主機接收到數據之后通過UART(115200)傳輸給電腦,使用串口調試助手(HEX)可以打開查看。

## 數據傳輸

使用IIC總線傳輸,經過我的調試,可以在8從機上穩定運行。

總共只需要4個線,2電源線和2數據線。

## 測試數據結果

懸空 0x00-0x10

黑 0x08-0x20

白 0xB0-0xFF

## 測試樣例

![示意圖](示意圖.jpg)

順時針方向分別是0和1號,也就是上圖中左邊是1、右邊是0;測得數據:

```MATLAB
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 15 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 15 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 15 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 15 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 14 13 01 00 31 AC D8 F2 EF C0 01 01
EC F2 C8 16 15 13 01 00 31 AC D8 F2 EF C0 01 01
```

數據格式:

\[數據*6](每個探頭的ADC轉換值,從左到右) \[發送成功所使用的的次數] \[從機地址]

- 位于白色上面的data\[0]\[0:3]給出了白色范圍內的值
- 位于黑色上面的data\[0]\[4:6]給出了黑色范圍內的值
- 位于過渡位置的data\[1]\[0]給出了中間值0x31,偏離過渡位置的data\[1]\[1]給出了比較靠近白色的值
- 位于白色上面的data\[1]\[2:6]給出了白色范圍內的值
- 所有傳輸均使用1次嘗試完成
- 可以連續運行10分鐘無故障

## 其他

經過測試,也可以比較好地分辨出紫色、藍色等。

## 總結

本次實驗比較成功,我設計的系統比較安全、靈敏、可靠、高效。

單片機源程序如下:
  1. #include <I2C.h>
  2. #include <STC15.h>
  3. #include <intrins.h>

  4. // #include "./include/delay.h"

  5. sbit LED         = P3 ^ 4;
  6. sbit I2C_SCL = P3 ^ 6;
  7. sbit I2C_SDA = P3 ^ 7;

  8. #if 0
  9. //定義LED燈引腳
  10. sbit Data[8] = {P37, P36, P35, P33, P32, P31, P30, P54};
  11. #endif

  12. void delay(unsigned int delay_time) // 1毫秒@22.1184MHz
  13. {
  14.         unsigned char i, j;
  15.         for (; delay_time > 0; delay_time--) {
  16.                 _nop_();
  17.                 _nop_();
  18.                 i = 22;
  19.                 j = 128;
  20.                 do {
  21.                         while (--j)
  22.                                 ;
  23.                 } while (--i);
  24.         }
  25. }

  26. void                  InitADC();
  27. unsigned char GetADCResult(unsigned char ch);

  28. #define ADC_POWER 0x80         // ADC電源控制位
  29. #define ADC_FLAG 0x10         // ADC完成標志
  30. #define ADC_START 0x08         // ADC起始控制位
  31. #define ADC_SPEEDLL 0x00 // 540個時鐘
  32. #define ADC_SPEEDL 0x20         // 360個時鐘
  33. #define ADC_SPEEDH 0x40         // 180個時鐘
  34. #define ADC_SPEEDHH 0x60 // 90個時鐘

  35. /*----------------------------
  36. 初始化ADC
  37. ----------------------------*/
  38. void InitADC() {
  39.         P1ASF          = 0xff; //設置P1口為AD口,0xff表示8通道全開
  40.         ADC_RES          = 0;          //清除結果寄存器
  41.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
  42.         delay(20); // ADC上電并延時
  43. }

  44. /*----------------------------
  45. 讀取ADC結果
  46. ----------------------------*/
  47. unsigned char GetADCResult(unsigned char ch) {
  48.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
  49.         _nop_(); //等待4個NOP
  50.         _nop_();
  51.         _nop_();
  52.         _nop_();
  53.         while (!(ADC_CONTR & ADC_FLAG))
  54.                 ;                                        //等待ADC轉換完成
  55.         ADC_CONTR &= ~ADC_FLAG; // Close ADC

  56.         return ADC_RES; //返回ADC結果
  57. }
  58. /*
  59. void test(void){
  60.                 while(1){
  61.                                 I2C_SCL=1;
  62.                                 delay(10);
  63.                                 I2C_SDA=1;
  64.                                 delay(10);
  65.                                 I2C_SCL=0;
  66.                                 delay(10);
  67.                                 I2C_SDA=0;
  68.                                 delay(10);
  69.                                 LED = !LED;
  70.                 }
  71. }*/

  72. /*----------------------------
  73. 主程序由此開始
  74. ----------------------------*/

  75. #define ADDR 0x17 //定義從機地址/編號

  76. unsigned char TX_data[2], ADC_data[8], i;

  77. void main() {
  78.         LED = 1;
  79.         InitADC();
  80.         delay(10);
  81.         while (1) {
  82.                 for (i = 0; i < 8; i++)
  83.                         ADC_data[7 - i] = GetADCResult(i);

  84.                 // TX_data[0] = 0; //初始化為沒有黑線
  85.                 // TX_data[1] = 0; //初始化為從第0個位置找到黑線
  86.                 // for (i = 0; i < 8; i++) {
  87.                 //         if (ADC_data[i] < 0x40) { //掃描到黑線
  88.                 //                 TX_data[1] = i;                                          //從第i個開始掃到黑線
  89.                 //                 i++;
  90.                 //                 TX_data[0]++; //掃描到黑線的數量
  91.                 //                 while (i < 8 && ADC_data[i] < 0x40) {
  92.                 //                         i++;
  93.                 //                         TX_data[0]++;
  94.                 //                 }
  95.                 //                 break;
  96.                 //         }
  97.                 // }

  98.                 // while (!I2C_Write(TX_data, ADDR, 2))
  99.                 //         ;
  100.                 P37 = ADC_data[0] > 0x38 ? 1 : 0;
  101.                 P36 = ADC_data[1] > 0x40 ? 1 : 0;
  102.                 P35 = ADC_data[2] > 0x40 ? 1 : 0;
  103.                 P33 = ADC_data[3] > 0x40 ? 1 : 0;
  104.                 P32 = ADC_data[4] > 0x40 ? 1 : 0;
  105.                 P31 = ADC_data[5] > 0x40 ? 1 : 0;
  106.                 P30 = ADC_data[6] > 0x40 ? 1 : 0;
  107.                 P54 = ADC_data[7] > 0x38 ? 1 : 0;
  108.                 delay(1);
  109.         }
  110. }
復制代碼

  1. #include "STC15.h"
  2. #include "./include/delay.h"
  3. #include <intrins.h>

  4. sbit LED = P3 ^ 4;

  5. #define I2CDelay() \
  6.         {              \
  7.                 _nop_();   \
  8.                 _nop_();   \
  9.                 _nop_();   \
  10.                 _nop_();   \
  11.         }
  12. sbit I2C_SCL = P3 ^ 6;
  13. sbit I2C_SDA = P3 ^ 7;

  14. /* I2C總線寫操作,dat-待寫入字節,返回值-主機應答位的值 */
  15. bit I2CWrite(unsigned char dat)
  16. {
  17.         bit ack;                        //用于暫存應答位的值
  18.         unsigned char mask; //用于探測字節內某一位值的掩碼變量

  19.         for (mask = 0x80; mask != 0; mask >>= 1) //從高位到低位依次進行
  20.         {
  21.                 if ((mask & dat) == 0) //該位的值輸出到SDA上
  22.                         I2C_SDA = 0;
  23.                 else
  24.                         I2C_SDA = 1;
  25.                 while (I2C_SCL == 0)
  26.                         ; //等待SCL上升沿
  27.                 while (I2C_SCL == 1)
  28.                         ; //等待SCL下降沿
  29.         }
  30.         I2C_SDA = 1; // 8位數據發送完后,從機釋放SDA,以檢測應答
  31.         while (I2C_SCL == 0)
  32.                 ;                   //等待SCL上升沿
  33.         ack = I2C_SDA; //讀取此時的SDA值,即為從機的應答值
  34.         while (I2C_SCL == 1)
  35.                 ; //等待SCL下降沿

  36.         return (~ack); //應答值取反以符合通常的邏輯:
  37.                                    // 0=不存在或忙或寫入失敗,1=存在且空閑或寫入成功
  38. }
  39. /* I2C總線讀操作,并發送非應答信號,返回值-讀到的字節 */
  40. unsigned char I2CReadNAK(unsigned char addr)
  41. {
  42.         unsigned char mask;
  43.         unsigned char dat = 0;

  44.         // I2C_SDA = 1;  //首先確保釋放SDA
  45.         // I2C_SCL = 1;  //首先確保釋放SDA
  46.         for (mask = 0x80; mask != 0; mask >>= 1) //從高位到低位依次進行
  47.         {
  48.                 while (I2C_SCL == 0)
  49.                         ;                          //等待SCL上升沿
  50.                 if (I2C_SDA == 0) //讀取SDA的值
  51.                         dat &= ~mask; //為0時,dat中對應位清零
  52.                 else
  53.                         dat |= mask; //為1時,dat中對應位置1
  54.                 while (I2C_SCL == 1)
  55.                         ; //等待SCL下降沿
  56.         }
  57.         if ((dat >> 1) == addr)
  58.                 I2C_SDA = 0; //地址正確,發送應答信號
  59.         else
  60.                 I2C_SDA = 1; //地址錯誤,發送非應答信號
  61.         while (I2C_SCL == 0)
  62.                 ; //等待SCL上升沿
  63.         while (I2C_SCL == 1)
  64.                 ; //等待SCL下降沿
  65.         I2C_SDA = 1;

  66.         return dat;
  67. }

  68. /* 讀取函數,buf-數據接收指針,addr-起始地址,len-讀取長度 */
  69. /*void I2C_Read(unsigned char *buf, unsigned char addr, unsigned char len)
  70. {
  71.         I2CStart();                //發送重復啟動信號
  72.         I2CWrite((addr<<1)|0x01);  //尋址器件,后續為讀操作
  73.         while (len > 1)            //連續讀取len-1個字節
  74.         {
  75.                 *buf++ = I2CReadACK(); //最后字節之前為讀取操作+應答
  76.                 len--;
  77.         }
  78.         *buf = I2CReadNAK();       //最后一個字節為讀取操作+非應答
  79.         I2CStop();
  80. }*/
  81. /* 寫入函數,buf-源數據指針,addr-起始地址,len-寫入長度 */
  82. bit I2C_Write(unsigned char *buf, unsigned char addr, unsigned char len) {
  83.         unsigned char I2C_SDA_new, I2C_SDA_old, get_addr; //,loop;
  84.         // I2C_SDA = 1;  //首先確保釋放SDA
  85.         // I2C_SCL = 1;  //首先確保釋放SCL
  86.         I2C_SDA_new = I2C_SDA;
  87.         do {
  88.                 do
  89.                         I2C_SDA_old = I2C_SDA_new;
  90.                 while (((I2C_SDA_new = I2C_SDA) == 1) ||
  91.                            (I2C_SDA_old == 0)); //等待SDA下降沿
  92.         } while (I2C_SCL == 0);                        //并且SCL為高電平
  93.         while (I2C_SCL == 1)
  94.                 ; //等待SCL下降沿

  95.         get_addr = (I2CReadNAK(addr) >> 1);

  96.         if (get_addr == addr) {
  97.                 LED = 1;

  98.                 while (len > 0) {
  99.                         I2CWrite(*buf++);
  100.                         // if(I2CWrite(*buf++)==0)break;     //寫入一個字節數據
  101.                         len--; //待寫入長度計數遞減
  102.                 }

  103.                 LED = 0;

  104.                 return 1; //發送成功
  105.         }
  106.         return 0; //發送失敗
  107. }
復制代碼

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人在线视 | 午夜小电影 | 国产精品久久片 | 婷婷福利 | 亚洲36d大奶网 | 九九伊人sl水蜜桃色推荐 | 欧美va大片 | 国产黄色大片在线观看 | 99视频免费播放 | 国产日韩一区 | 91精品国产综合久久香蕉麻豆 | 日韩不卡一区二区 | 午夜一级做a爰片久久毛片 精品综合 | 精品欧美一区二区在线观看 | 在线观看中文字幕视频 | 国产精品乱码一区二区三区 | 亚洲aⅴ| 91精品久久久久 | 免费一区 | 久久成人在线视频 | 日韩a在线 | 精品国产一区二区三区性色av | 欧美一级片在线看 | 久久婷婷国产麻豆91 | 国产伦精品一区二区三毛 | 欧美在线 | 欧美中文字幕 | 色综合av| 国产农村妇女毛片精品久久麻豆 | 中文字幕av高清 | 亚洲国产精品久久 | 三级在线视频 | 欧美日韩美女 | 久久久久国产精品午夜一区 | www.久久久| 久久久久久久久毛片 | 81精品国产乱码久久久久久 | 日本精a在线观看 | 久久三区| 中文字幕第二十页 | 精品久久久久久久人人人人传媒 |