使用单片机型号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
## 测试样例

顺时针方向分别是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分钟无故障
## 其他
经过测试,也可以比较好地分辨出紫色、蓝色等。
## 总结
本次实验比较成功,我设计的系统比较安全、灵敏、可靠、高效。
单片机源程序如下:
- #include <I2C.h>
- #include <STC15.h>
- #include <intrins.h>
- // #include "./include/delay.h"
- sbit LED = P3 ^ 4;
- sbit I2C_SCL = P3 ^ 6;
- sbit I2C_SDA = P3 ^ 7;
- #if 0
- //定义LED灯引脚
- sbit Data[8] = {P37, P36, P35, P33, P32, P31, P30, P54};
- #endif
- void delay(unsigned int delay_time) // 1毫秒@22.1184MHz
- {
- unsigned char i, j;
- for (; delay_time > 0; delay_time--) {
- _nop_();
- _nop_();
- i = 22;
- j = 128;
- do {
- while (--j)
- ;
- } while (--i);
- }
- }
- void InitADC();
- unsigned char GetADCResult(unsigned char ch);
- #define ADC_POWER 0x80 // ADC电源控制位
- #define ADC_FLAG 0x10 // ADC完成标志
- #define ADC_START 0x08 // ADC起始控制位
- #define ADC_SPEEDLL 0x00 // 540个时钟
- #define ADC_SPEEDL 0x20 // 360个时钟
- #define ADC_SPEEDH 0x40 // 180个时钟
- #define ADC_SPEEDHH 0x60 // 90个时钟
- /*----------------------------
- 初始化ADC
- ----------------------------*/
- void InitADC() {
- P1ASF = 0xff; //设置P1口为AD口,0xff表示8通道全开
- ADC_RES = 0; //清除结果寄存器
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
- delay(20); // ADC上电并延时
- }
- /*----------------------------
- 读取ADC结果
- ----------------------------*/
- unsigned char GetADCResult(unsigned char ch) {
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
- _nop_(); //等待4个NOP
- _nop_();
- _nop_();
- _nop_();
- while (!(ADC_CONTR & ADC_FLAG))
- ; //等待ADC转换完成
- ADC_CONTR &= ~ADC_FLAG; // Close ADC
- return ADC_RES; //返回ADC结果
- }
- /*
- void test(void){
- while(1){
- I2C_SCL=1;
- delay(10);
- I2C_SDA=1;
- delay(10);
- I2C_SCL=0;
- delay(10);
- I2C_SDA=0;
- delay(10);
- LED = !LED;
- }
- }*/
- /*----------------------------
- 主程序由此开始
- ----------------------------*/
- #define ADDR 0x17 //定义从机地址/编号
- unsigned char TX_data[2], ADC_data[8], i;
- void main() {
- LED = 1;
- InitADC();
- delay(10);
- while (1) {
- for (i = 0; i < 8; i++)
- ADC_data[7 - i] = GetADCResult(i);
- // TX_data[0] = 0; //初始化为没有黑线
- // TX_data[1] = 0; //初始化为从第0个位置找到黑线
- // for (i = 0; i < 8; i++) {
- // if (ADC_data[i] < 0x40) { //扫描到黑线
- // TX_data[1] = i; //从第i个开始扫到黑线
- // i++;
- // TX_data[0]++; //扫描到黑线的数量
- // while (i < 8 && ADC_data[i] < 0x40) {
- // i++;
- // TX_data[0]++;
- // }
- // break;
- // }
- // }
- // while (!I2C_Write(TX_data, ADDR, 2))
- // ;
- P37 = ADC_data[0] > 0x38 ? 1 : 0;
- P36 = ADC_data[1] > 0x40 ? 1 : 0;
- P35 = ADC_data[2] > 0x40 ? 1 : 0;
- P33 = ADC_data[3] > 0x40 ? 1 : 0;
- P32 = ADC_data[4] > 0x40 ? 1 : 0;
- P31 = ADC_data[5] > 0x40 ? 1 : 0;
- P30 = ADC_data[6] > 0x40 ? 1 : 0;
- P54 = ADC_data[7] > 0x38 ? 1 : 0;
- delay(1);
- }
- }
复制代码
|