一: 内容介绍
基于TN9传感器,设计一个非接触人体温度测量系统,完成以下内容:
(1) 给出硬件逻辑图
(2) 编写温度采集程序
(3) 在LCD上显示温度值
1.组成框图
2.工作原理
V:电源
D:数据
C:时钟 (2KHz)
G:接地
A:测试脚 (低电平时连续测试物体温度)
宏定义
#define TN9_GPIO GPIOD
#define TN9_CLK_PIN GPIO_Pin_14
#define TN9_DAT_PIN GPIO_Pin_15
#define TN9_PIN_A GPIO_Pin_0
#define TN9_CLK GPIO_ReadInputDataBit(TN9_GPIO,TN9_CLK_PIN)
#define TN9_DAT GPIO_ReadInputDataBit(TN9_GPIO,TN9_DAT_PIN)
#define TN9_A_LOW GPIO_ResetBits(TN9_GPIO,TN9_PIN_A)
#define TN9_A_HIGH GPIO_SetBits(TN9_GPIO,TN9_PIN_A)
前置知识介绍:
C语言提供了6种位运算:
假设 uint8_t 或者 char (都是1字节 = 8b) 信息如下:
value1 = 0101 1011 value2=1001 1010 分别进行以下运算
(1) & 按位与 规则: 0&0=0 0&1=0 1&1=1
0101 1011
& 1001 1010
result = 0001 1010
(2) | 按位或 规则: 0|0=0 0|1=1 1|1=1
0101 1011
| 1001 1010
result = 1101 1011
(3) ^ 按位异或 规则: 0^0=0 0^1=1 1^1=0
0101 1011
^ 1001 1010
result = 1100 0001
(4) ~ 取反 规则: ~0=1 ~1=0
~0101 1011
result = 1010 0100
(5)<< 左移 所有二进制左移,空位补0
0101 1011 << 1 左移一位
result = 1011 011(0)
(6)>> 右移 所有二进制右移,空位补0
0101 1011 >>2 右移两位
result = (00)01 0110
(1)当时钟是低电平的时候,进行采样获取数据 1bit
原因: 当上升沿时,高电平时的数据不稳定,所以不进行采样;当低电平时,数据稳定,所以获取该数据
(2)连续获得8b组成一字节作为数据初始化部分信息;
(3)当采取 5B 时,信息的初始化结束
具体代码如下
获取数据函数
uint8_t TN9_ReadByte(void){
uint8_t value = 0;
uint32_t i;
for(i = 0; i < 8; i++){
while(TN9_CLK ==1 ); // 如果时钟是高电平,那么持续循环不采样
value <<=1; // 将数据左移1bit
value |=TN9_DAT; // 与数据传来的信息,按位或
while(TN9_CLK ==0); // 如果时钟是低电平,那么持续循环
} // 持续8次 获取 1B 信息时结束循环
return value; // 将信息返回
}
代码中:
左移一位后,低位最后一位补0,然后与TN9_DAT的数据 按位或: 如果数据为1 那么结果就是1,如果数据为0 那么结果就是0
无形中,将传来的数据位,加入了 value
一共进行获取数据5次 即获取40个bit位
数据分别传入: Item MSB LSB Sum CR 组成信息格式
Item MSB LSB Sum CR Item: ' L ' (4CH): Tobj (目标温度) ' f '(66H): Tamb (环境温度)
MSB: 8 bit Data 最高有效位
LSB: 8 bit Data最低有效位
Sum: Item+MSB+LSB=Sum
CR: 0DH ——> 回车表示结束信息
/*
原型: void TN9_Init(void);
描述: TN9传感器信号初始化
输入参数: 无
输出参数:
temp 无符号16位整型 代表温度值
返回值:
0 代表目标温度
1 代表环境温度
0xFF 代表错误
*/
uint8_t TN9_ReadReport(uint16_t *temp){
uint8_t buff[5]; // 存储数据信息 即 Item MSB LSB Sum CR
uint32_t i;
uint8_t result; // 结果
TN9_A_LOW; // 开始获取信息
for(i = 0; i < 5; i++)
buff[i] = TN9_ReadByte(); // 每次读取一字节内存存储到buff
TN9_A_HIGH; // 停止获取信息
if(buff[4]==0xd){ // 如果CR中的内容是 0xd 表示上述读取信息结束
//将Item+MSB+LSB 与 Sum 比较验证信息正误
if((buff[0] + buff[1] + buff[2]) == buff[3]){
// 信息拼接: (MSB)高位左移8位将(LSB)低位信息补充 组合成完整信息
// 为了避免小数,所以 * 100 后面就是计算公式了
*temp = ((((buff[1]<<8) + buff[2])*100)/16)-27315;
if(buff[0] == 'L') // 如果Item 信息是 "L" 表明 目标温度 否则为环境温度
result = 0;
else
result = 1;
}else{
result = 0xff; // 信息错误
}
}else{
result = 0xff; // 信息错误
}
return result; // 结束
}
int main(){
uint16_t temp;
uint32_t timeOut;
char tmpBuf[128];
Systick_Init();
TN9_Init();
USART3_Config();
USART_PutString(USART3,"XXX");
timeOut = Get_Time1ms_Cnt();
while(1){
if((Get_Time1ms_Cnt() - timeOut) > 1000){
timeOut = Get_Time1ms_Cnt();
switch(TN9_ReadReport(&temp)){
case 0:
sprintf(tmpBuf,"目标温度是: %d.%d\n",temp/100,temp%100);
USART_PutString(USART3,tmpBuf); // 通信传输
speechSyn(tmpBuf); // 语音播报
break;
case 1:
sprintf(tmpBuf,"环境温度是: %d.%d\n",temp/100,temp%100);
USART_PutString(USART3,tmpBuf);
speechSyn(tmpBuf);
break;
default:
USART_PutString(USART3,"这是错哒\n");
break;
}
}
}
}