AT32F415+TH09+BSP库
实现需了解:
1.IIC协议的软件模拟。本文不多介绍,跟着这篇学)
IIC
2. 启动传感器采集
3. 传感器时序图的理解与代码实现
4. 传感器的CRC检验理解与代码实现
懒得复制,基于master,参考上面链接编写
首先查手册获得两个地址,(1)IIC从机地址,即传感器设备的地址(2)传感器启动温湿度采集的寄存器地址
#define TH09_ADDR 0X43
#define START_REG 0X22
还需明确,TH09_ADDR 只是7 bit ,最低位来确定操作是读(1)还是写(0)
0x43<<1 =0x86
read = 0x86 | 1
write = 0x86 |0
SENS_START 寄存器有2 bit,分别设置温度与湿度,需设置两个为1,即应该通过IIC接口向TH09(0X43)的SENS_START (0x22)的写入(0)data(0x03)来启动温湿度采集。
代码实现如下:
uint8_t BSP_IIC_writeReg(uint8_t i2cId, uint8_t addr, uint8_t reg, uint8_t *pData, uint16_t len)
{
/* 发送起始信号 */
BSP_I2C_Start(i2cId);
/* 发送地址 W */
BSP_I2C_Send_Byte(i2cId, addr | I2C_WR ); // 7位地址和1位写(0)
if (BSP_I2C_waitAck(i2cId) == 0) {
return (0);
}
/* 发送寄存器地址 */
BSP_I2C_Send_Byte(i2cId, reg);
if (BSP_I2C_waitAck(i2cId) == 0) {
return (0);
}
/* 发送数据 */
for (uint16_t i = 0; i < len; i++) {
BSP_I2C_Send_Byte(i2cId, pData[i]);
if (BSP_I2C_waitAck(i2cId) == 0) {
return (0);
}
}
// DEBUG("PData : %02x \r\n",pData[0]);// 03 没错
BSP_I2C_Stop(i2cId);
return (1);
}
这边是要去读取slave(TH09)采集的温湿度数据,看(b)。
读取事务首先从写寄存器开始,这个寄存器为存储采集温湿度数据的T_VAL和H_VAL寄存器。
写结束后有一个s表示sleep,需要给时间让传感器对采集数据进行处理,如果没有sleep可能得到的采集数据会出错。
之后就是一个字节读然后等ack,最后一帧不需要回复ack。
时序图实现就是对着图用IIC的代码进行看图写话。代码实现:
uint8_t BSP_IIC09_readData(uint8_t i2cId, uint8_t addr,uint8_t reg,uint8_t *pData, uint16_t len){
/* 发送起始信号 */
BSP_I2C_Start(i2cId);
/* 发送地址 R */
BSP_I2C_Send_Byte(i2cId, addr | I2C_WR);
// DEBUG("slave addr : %02x \r\n",addr | I2C_WR);
/* 等待应答 */
if (BSP_I2C_waitAck(i2cId) == 0) {
return (0);
}
/* 发送寄存器地址 */
BSP_I2C_Send_Byte(i2cId, reg);// 写read reg的地址0x30
// DEBUG("reg addr : %02x \r\n",reg);
/* 等待应答 */
if (BSP_I2C_waitAck(i2cId) == 0) {
return (0);
}
/* 发送起始信号 */
BSP_I2C_Start(i2cId);
/* 发送地址 R */
BSP_I2C_Send_Byte(i2cId, addr | I2C_RD);// I2C_RD 1 为读,设置读取位
// DEBUG("slave addr : %02x \r\n",addr | I2C_RD);
/* 等待应答 */
if (BSP_I2C_waitAck(i2cId) == 0) {
return (0);
}
for (uint16_t i = 0; i < len; i++) {
if (i == (len - 1)) {
pData[i] = BSP_IIC_Read_Byte(i2cId, 0); /* 最后一个字节不发送应答指令 */
// DEBUG("PData : %02x \r\n",pData[i]);
}
else {
pData[i] = BSP_IIC_Read_Byte(i2cId, 1);
}
}
BSP_I2C_Stop(i2cId);
return (1);
}
data = ((uint16_t)i2c_receiver[1] << 8) | i2c_receiver[0];
val_tmp = (uint16_t)i2c_receiver[2]&0x1;
val = val_tmp<<16|data;
nt TH09_crc7_check(uint32_t data,uint32_t crc) {
uint32_t crc_result =0 ;
uint8_t crc_true = crc >> 1; // 有一位是valid
crc_result = crc7_compute(data); //使用data计算出crc。然后与原始比较
// DEBUG("data: %02x\r\n", data);
// DEBUG("crc: %02x\r\n", crc);
// DEBUG("crc_result: %02x\r\n", crc_result);
// 返回 CRC-7 结果 与 CRC比较
if(crc_true == crc_result){
return 1;
}
else{
return 0;
}
}
crc7_compute部分参考TH09手册。
//CRC related
#define CRC7WIDTH 7
#define CRC7POLY 0x89 // 二项式
#define CRC7IVEC 0x7F // 0111 1111
#define DATA7WIDTH 17
#define DATA7MASK ((1UL << DATA7WIDTH) - 1) // 0 1111 1111 1111 1111
#define DATA7MSB (1UL << (DATA7WIDTH - 1)) // 1 0000 0000 0000 0000
uint32_t crc7_compute(uint32_t crcData){
uint32_t bit = DATA7MSB; // 循环变量(指示要测试哪一位,从最高位开始)
uint32_t pol = CRC7POLY;
pol = pol << (DATA7WIDTH - CRC7WIDTH - 1); //设置多项式
//留空间给crc value
crcData = crcData << CRC7WIDTH;
bit = bit << CRC7WIDTH; //最高位为1
pol = pol << CRC7WIDTH;
// 插入初始向量
crcData |= CRC7IVEC; //7位1加到低位
// DEBUG("crcData2:%02x\r\n",crcData);
// 这边crc算了24位
// CRC 算法的主要循环
while (bit & (DATA7MASK << CRC7WIDTH)) {
// 如果位为1,执行异或操作
if (bit & crcData){ //该位不为0
crcData ^= pol;
}
// 位右移一位
bit >>= 1;
// 多项式右移一位
pol >>= 1;
}
return crcData; //7位crc校验值
}
采集数据使用数码管显示。
使用SecureCRT在终端显示采集数据。为了采集数据的小数位输出,扩大了10倍。