doubao_chat/apps/common/example/peripheral/one_way/ds18b20_am2301.c

899 lines
28 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "app_config.h"
#include "system/includes.h"
#include "os/os_api.h"
#include "asm/clock.h"
#define TEMP_SAMPLE_TIMER (500) //温度采样时间ms,建议大于100ms以上
#define TEMP_MAX (125) //传感器上限显示温度
#define TEMP_MIN (-55) //传感器下限显示温度
#define TEMP_FILTER_CNT (20) //启动时过滤数据次数(启动时有数据不正常,则需要打开过滤,过滤次数看情况而定)
#define TEMP_RANK_NUM (9) //中值滤波使用温度数据个数,冒泡排序过滤大小值,最后取中间值
#define SENSOR_CHECK_CNT (5) //传感器检测失败次数定为传感器掉线
#define USER_FUNC_INT_SRAM 1 //中断处理函数是否放在内部sram
#if USER_FUNC_INT_SRAM
#define FUNC_IN SEC_USED(.volatile_ram_code)
#else
#define FUNC_IN
#endif
#define AWINLINE __attribute__((always_inline))
//单总线硬件IO配置
#define wire_1_bit BIT(7) //IO口,只能寄存器操作
#define DQ_INIT {JL_PORTA->DIR &= ~wire_1_bit;JL_PORTA->PU &= ~wire_1_bit;JL_PORTA->PD &= ~wire_1_bit;}//务必关闭内部上下拉
#define DQ_OUT {JL_PORTA->DIR &= ~wire_1_bit;}
#define DQ_IN {JL_PORTA->DIR |= wire_1_bit;}
#define DQ_R ((JL_PORTA->IN & wire_1_bit) ? 1 : 0)
#define DQ_W_H JL_PORTA->OUT |= wire_1_bit
#define DQ_W_L JL_PORTA->OUT &=~ wire_1_bit
//#define db_io BIT(0) //IO口,只能寄存器操作
//#define DB_INIT {JL_PORTH->DIR &= ~db_io;JL_PORTH->HD |= db_io;}
//#define DB_H JL_PORTH->OUT |= db_io
//#define DB_L JL_PORTH->OUT &=~ db_io
//#define DB_AND JL_PORTH->OUT ^= db_io
enum {
TMP_ERR = 0,
TMP_NONE,
TMP_INIT_START,
TMP_INIT_ACK,
TMP_INIT_ERR,
TMP_INIT_OK,
TMP_WTITE_BYTE_START,
TMP_WTITE_BYTE_ERR,
TMP_WTITE_BYTE_OK,
TMP_READ_BYTE_START,
TMP_READ_BYTE_ERR,
TMP_READ_BYTE_OK,
};
enum read_temp_step {
STEP_SEND_INIT = 0,
STEP_SEND_0XCC1,
STEP_SEND_0X44,
STEP_SEND_REINIT,
STEP_SEND_0XCC2,
STEP_SEND_0XBE,
STEP_READ_BYT_L,
STEP_READ_BYT_H,
STEP_READ_DATA_OK,
STEP_READ_REDO,
};
enum read_temp_am2301_step {
STEP_AM_SEND_INIT = 0,
STEP_AM_SEND_READ,
STEP_AM_SEND_REINIT,
STEP_AM_READ_DATA_OK,
STEP_AM_READ_REDO,
};
enum sensor_type {
SENSOR_ERR = -1,
SENSOR_NONE = 0,
SENSOR_DS1B820,
SENSOR_AM2301,
};
struct temp_strut {
volatile u8 mode_type;
volatile u8 mode_cnt;
volatile u8 byte_num;
volatile u8 temp_h;
volatile u8 temp_l;
volatile enum read_temp_step read_step;
volatile u8 write_data;
volatile u8 read_data;
volatile u8 wr_bit;
u16 temp;
u16 filter_cnt;
u8 ftemp_rank_id;
float ftemp;//温度
float fhumidity;//湿度
volatile float ftemp_rank[TEMP_RANK_NUM];
volatile u8 recv_data[5];//D温湿度传感器
u8 is_ds18b20;//DS1B820温度计
u8 timer_close;
char sensor_type;
u8 sensor_check;
u32 ready_readed_tocnt;//没有被读数据超时计数
} temp_info = {0};
static JL_TIMER_TypeDef *TMR = JL_TIMER4;//选择定时器4
static u8 timer_irq = IRQ_TIMER4_IDX;//选择定时器4
static const u8 timer_index[16] = {0, 4, 1, 5, 2, 6, 3, 7, 8, 12, 9, 13, 10, 14, 11, 15};
static const u32 timer_table[16] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
static u32 timer_clk = 0;
static FUNC_IN ___interrupt void ds18b20_timer_isr(void);
static FUNC_IN ___interrupt void am2301_timer_isr(void);
static AWINLINE float temp_rank(float *buff, u8 lenth)//up rank
{
u8 i, j;
float temp;
for (i = 0; i < lenth - 1; i++) {
for (j = 0; j < lenth - 1 - i; j++) {
if (buff[j] > buff[j + 1]) {
temp = buff[j + 1];
buff[j + 1] = buff[j];
buff[j] = temp;
}
}
}
temp = (lenth % 2) ? buff[lenth / 2] : (buff[lenth / 2] + buff[lenth / 2 - 1]) / 2;
return temp;//奇个数返回中间数值,偶个数返回中间2个值平均值
}
static AWINLINE void timer_cfg(u32 freq, u32 us)
{
u32 clock = timer_clk;
u8 psc = 0;
u8 tmp = 0;
u32 prd = 0;
u32 ts = us / (1000 * 1000);//计算秒
u32 tu = us % (1000 * 1000);//计算秒剩余us
u8 i;
float tp = 0;
if (freq >= clock) {
freq = clock;
} else if (freq <= 1) {
freq = 1;
if (ts) {
tp = (float)tu / (1000 * 1000);
}
}
/*求prd值*/
prd = clock / freq;
if (prd > 65535) {
for (psc = 0; psc < 16; psc++) {
prd = (u32)(clock / (timer_table[psc]) / freq);
if (prd <= 65535) {
break;
} else if (psc == 15) {
prd = 65535;
break;
}
}
}
prd = ts ? (prd * ts + tp * prd) : prd;
psc = timer_index[psc];
TMR->CON = 0;
TMR->CNT = 0;
TMR->CON |= BIT(14);
TMR->PRD = prd;
TMR->CON |= psc << 4; //lsb_clk分频
TMR->CON |= BIT(0);
}
static AWINLINE void timer_init(u32 us)
{
u32 freq = 1000000 / us;
timer_cfg(freq, us);
}
/*****************************************************************************
DS18B20初始化
*****************************************************************************/
static AWINLINE void temp_mode_reinit(void)
{
temp_info.byte_num = 0;
temp_info.mode_cnt = 0;
temp_info.wr_bit = 0;
temp_info.timer_close = 0;
temp_info.mode_type = TMP_NONE;
}
static AWINLINE void ds18b20_timer_exit(void)
{
if (!(TMR->CON & BIT(15))) {
TMR->CON &= ~BIT(0);
} else {
temp_info.timer_close = TRUE;
}
}
static AWINLINE void ds18b20_timer_init(void)
{
timer_clk = clk_get("timer");
temp_info.sensor_check = 0;
temp_info.sensor_type = SENSOR_NONE;
temp_info.mode_type = TMP_NONE;
temp_info.read_step = STEP_SEND_INIT;
temp_mode_reinit();
request_irq(timer_irq, 3, ds18b20_timer_isr, 0);
timer_init(50 * 1000); //初始化50ms检测一次设备
}
static AWINLINE void ds18b20_io_init(void)
{
DQ_OUT;
DQ_W_H;
// printf("ds18b20_io_init\n");
}
static AWINLINE void temp_redo_next_time(u32 us)
{
DQ_OUT;
DQ_W_H;
timer_init(us);//下次检测温度时间
}
static AWINLINE void temp0_reset(void)//高电平空闲信号
{
DQ_OUT;
timer_init(10 * 1000); //10ms空闲信号
DQ_W_H;
}
static AWINLINE void temp1_reset_start(void)//启动复位信号
{
timer_init(600);//拉低600us复位信号
DQ_W_L;
}
static AWINLINE void temp2_release_bus(void)
{
timer_init(65);//释放总线,等待60us (15 - 60us)
DQ_IN;
}
static AWINLINE u8 temp3_reset_get_ack(void)//复位信号从机的ACK是否正常
{
u8 ack = !DQ_R;
timer_init(480);//等待,最低480us
if (!ack) { //检测ACK完成
temp_redo_next_time(50 * 1000); //检测失败,等下一次检测,50ms
}
return ack;
}
static AWINLINE void temp4_reset_end(void)
{
DQ_OUT;
DQ_W_H;
timer_init(10);//10us后读写字节
}
static FUNC_IN u8 ds18b20_init(void)
{
u8 ret;
if (temp_info.mode_type == TMP_INIT_OK) {
return TMP_INIT_OK;
}
temp_info.mode_type = (temp_info.mode_type == TMP_INIT_ACK) ? temp_info.mode_type : TMP_INIT_START;
switch (temp_info.mode_cnt) {
case 0:
temp0_reset();
break;
case 1:
temp1_reset_start();
break;
case 2:
temp2_release_bus();
break;
case 3:
ret = temp3_reset_get_ack();
temp_info.mode_type = ret ? TMP_INIT_ACK : TMP_INIT_ERR;
if (!ret) {
temp_info.mode_cnt = 0;
if (++temp_info.sensor_check > SENSOR_CHECK_CNT) {
temp_info.sensor_type = SENSOR_ERR;
temp_info.sensor_check = 0;
}
}
break;
case 4:
temp4_reset_end();
temp_info.mode_type = TMP_INIT_OK;
temp_info.mode_cnt = 0;
temp_info.sensor_check = 0;
temp_info.sensor_type = SENSOR_DS1B820;
return temp_info.mode_type;
default:
break;
}
temp_info.mode_cnt++;
return temp_info.mode_type;
}
/*****************************************************************************
DS18B20读写字节
*****************************************************************************/
static AWINLINE void temp_write_start_bit(void)
{
DQ_OUT;
timer_init(10);//最高15us要拉低
DQ_W_L;
}
static AWINLINE void temp_write_end_bit(u8 bit)
{
timer_init(60);//延时60us,60 - 120us
if (bit) {
DQ_W_H;
} else {
DQ_W_L;
}
}
static AWINLINE void temp_write_bit_complet(void)
{
timer_init(10);//5us后继续读写写一个bit,> 1us
DQ_W_H;
}
static AWINLINE void temp_read_start_bit(void)
{
DQ_OUT;
timer_init(1);//要拉低最低1us
DQ_W_L;
}
static AWINLINE void temp_read_release_bus(void)
{
DQ_IN;
timer_init(10);//15us之内采样
}
static AWINLINE u8 temp_read_end_bit(void)
{
u8 bit;
bit = DQ_R;
timer_init(60);//延时60us,60 - 120us
return bit;
}
static AWINLINE void temp_read_bit_complet(void)
{
timer_init(10);//10us后继续读写写一个bit,> 1us
DQ_OUT;
DQ_W_H;
}
static FUNC_IN u8 ds18b20_write_byte(u8 byte)
{
if (temp_info.mode_type == TMP_WTITE_BYTE_OK) {
return TMP_WTITE_BYTE_OK;
}
if (!temp_info.mode_cnt && !temp_info.wr_bit) {
temp_info.write_data = byte;
}
temp_info.mode_type = TMP_WTITE_BYTE_START;
switch (temp_info.wr_bit) {
case 0:
temp_write_start_bit();
break;
case 1:
temp_write_end_bit(temp_info.write_data & 0x1);
break;
case 2:
temp_write_bit_complet();
temp_info.write_data >>= 1;
default:
break;
}
temp_info.wr_bit++;
if (temp_info.wr_bit > 2) { //最大步骤是0-2
temp_info.mode_cnt++;
temp_info.wr_bit = 0;
}
if (temp_info.mode_cnt >= 8) {
temp_info.mode_type = TMP_WTITE_BYTE_OK;
temp_info.mode_cnt = 0;
temp_info.wr_bit = 0;
temp_info.write_data = 0;
}
return temp_info.mode_type;
}
static FUNC_IN u8 ds18b20_read_byte(void)
{
u8 ret;
if (temp_info.mode_type == TMP_READ_BYTE_OK) {
return TMP_READ_BYTE_OK;
}
if (!temp_info.mode_cnt && !temp_info.wr_bit) {
temp_info.read_data = 0;
}
temp_info.mode_type = TMP_READ_BYTE_START;
switch (temp_info.wr_bit) {
case 0:
temp_read_start_bit();
temp_info.read_data >>= 1;
break;
case 1:
temp_read_release_bus();
break;
case 2:
ret = temp_read_end_bit();
temp_info.read_data |= ret ? 0x80 : 0x0;
break;
case 3:
temp_read_bit_complet();
default:
break;
}
temp_info.wr_bit++;
if (temp_info.wr_bit > 3) { //最大步骤是0-3
temp_info.mode_cnt++;
temp_info.wr_bit = 0;
}
if (temp_info.mode_cnt >= 8) {
temp_info.mode_type = TMP_READ_BYTE_OK;
temp_info.mode_cnt = 0;
temp_info.wr_bit = 0;
temp_info.write_data = 0;
}
return temp_info.mode_type;
}
u8 ds18b20_temp_read(float *temp_buf)//线程读取温度数据,temp_buf :温度数据存储地址
{
if (temp_info.read_step == STEP_READ_DATA_OK) { //ds18b20温度读取正常
*temp_buf = temp_info.ftemp;
temp_info.read_step = STEP_READ_REDO;//重新读取温度标记
return 1;
}
return 0;
}
/*****************************************************************************
DS18B20中断处理函数
*****************************************************************************/
static FUNC_IN ___interrupt void ds18b20_timer_isr(void)
{
if (TMR->CON & BIT(15)) {
//读取温度步骤
switch (temp_info.read_step) {
case STEP_SEND_INIT:
ds18b20_init(); //1.初始化
break;
case STEP_SEND_0XCC1:
ds18b20_write_byte(0xCC); //2,忽略ROM指令
break;
case STEP_SEND_0X44:
ds18b20_write_byte(0x44); //3.温度转换指令
break;
case STEP_SEND_REINIT:
ds18b20_init(); //4.初始化
break;
case STEP_SEND_0XCC2:
ds18b20_write_byte(0xCC); //5.忽略ROM指令
break;
case STEP_SEND_0XBE:
ds18b20_write_byte(0xBE); //6.读寄存器指令
break;
case STEP_READ_BYT_L:
ds18b20_read_byte(); //7.读取低字节
break;
case STEP_READ_BYT_H:
ds18b20_read_byte(); //8.读取高字节
break;
case STEP_READ_REDO:
temp_info.read_step = STEP_SEND_INIT;
if (temp_info.filter_cnt < TEMP_FILTER_CNT || (temp_info.ftemp_rank_id && temp_info.ftemp_rank_id < TEMP_RANK_NUM)) { //启动时过滤,存储在排序BUFF快速读取
timer_init(2 * 1000); //2ms快速过滤
} else {
timer_init(TEMP_SAMPLE_TIMER * 1000); //下次检测温度时间
}
break;
default:
break;
}
//读写一个字节结果分析
switch (temp_info.mode_type) {
case TMP_INIT_OK:
if (temp_info.read_step == STEP_SEND_INIT) {
temp_info.read_step = STEP_SEND_0XCC1;
} else {
temp_info.read_step = STEP_SEND_0XCC2;
}
temp_mode_reinit();
break;
case TMP_WTITE_BYTE_OK:
if (temp_info.read_step == STEP_SEND_0XCC1) {
temp_info.read_step = STEP_SEND_0X44;
} else if (temp_info.read_step == STEP_SEND_0X44) {
temp_info.read_step = STEP_SEND_REINIT;
} else if (temp_info.read_step == STEP_SEND_0XCC2) {
temp_info.read_step = STEP_SEND_0XBE;
} else if (temp_info.read_step == STEP_SEND_0XBE) {
temp_info.read_step = STEP_READ_BYT_L;
}
temp_mode_reinit();
break;
case TMP_READ_BYTE_OK:
if (temp_info.read_step == STEP_READ_BYT_L) {
temp_info.read_step = STEP_READ_BYT_H;
temp_info.temp_l = temp_info.read_data;
} else {
temp_info.temp_h = temp_info.read_data;
temp_info.temp = (temp_info.temp_h << 8) | temp_info.temp_l;
temp_info.ftemp = (float)temp_info.temp / 16;//* 0.0625;//温度转换
if ((temp_info.filter_cnt >= TEMP_FILTER_CNT || !TEMP_FILTER_CNT) && //过滤完成或者无过滤
(temp_info.ftemp > TEMP_MIN && temp_info.ftemp < TEMP_MAX)) { //ds18b20温度正常范围
temp_info.ftemp_rank[temp_info.ftemp_rank_id++] = temp_info.ftemp;
if (temp_info.ftemp_rank_id >= TEMP_RANK_NUM) {
temp_info.read_step = STEP_READ_DATA_OK;//读取完成
temp_info.ftemp = temp_rank(temp_info.ftemp_rank, TEMP_RANK_NUM);//中值滤波
temp_info.ftemp_rank_id = 0;
} else {
temp_info.read_step = STEP_READ_REDO;//重新检测
}
temp_redo_next_time(2 * 1000);
} else {
if (TEMP_FILTER_CNT) {
temp_info.filter_cnt++;
}
temp_info.read_step = STEP_READ_REDO;//重新检测
temp_redo_next_time(10 * 1000); //10ms后检测线程是否读取温度结果
}
}
temp_mode_reinit();
break;
case TMP_ERR:
case TMP_INIT_ERR:
case TMP_WTITE_BYTE_ERR:
case TMP_READ_BYTE_ERR:
temp_info.read_step = STEP_SEND_INIT;
temp_info.filter_cnt = 0;
temp_info.ftemp_rank_id = 0;
temp_mode_reinit();
temp_redo_next_time(50 * 1000); //下次检测温度
break;
default :
break;
}
if (temp_info.timer_close) {
temp_info.timer_close = 0;
TMR->CON &= ~BIT(0);
}
TMR->CON |= BIT(14);
}
}
/*************************************************************************************************************************************************************/
/*****************************************************************************
AM2301初始化
*****************************************************************************/
#define AM2301_DATA_L_TIMER 58 //数据0/1低电平时间58 - 62 us,取最小值,示波器抓出来的,文档不对应
#define AM2301_DATA1_H_TIMER 72 //数据1高电平时间72 - 76 us,取最小值,示波器抓出来的,文档不对应
static AWINLINE void am2301_timer_init(void)
{
timer_clk = clk_get("timer");
temp_info.sensor_check = 0;
temp_info.sensor_type = SENSOR_NONE;
temp_info.mode_type = TMP_NONE;
temp_info.read_step = STEP_AM_SEND_INIT;
temp_mode_reinit();
request_irq(timer_irq, 3, am2301_timer_isr, 0);
timer_init(50 * 1000); //初始化100ms检测一次设备
}
static AWINLINE void am2301_timer_exit(void)
{
if (!(TMR->CON & BIT(15))) {
TMR->CON &= ~BIT(0);
} else {
temp_info.timer_close = TRUE;
}
}
static AWINLINE void am2301_io_init(void)
{
DQ_OUT;
DQ_W_H;
// printf("am2301_io_init\n");
}
static AWINLINE void am2301_temp_redo_next_time(u32 us)
{
DQ_OUT;
DQ_W_H;
timer_init(us);//下次检测温度时间
}
static AWINLINE void am2301_temp0_reset(void)//高电平空闲信号
{
timer_init(10 * 1000); //10ms空闲信号
DQ_OUT;
DQ_W_H;
}
static AWINLINE void am2301_temp1_reset_start(void)//启动复位信号
{
timer_init(1000);//拉低>800us复位信号
DQ_W_L;
}
static AWINLINE void am2301_temp2_release_bus(void)//启动复位信号
{
timer_init(30);//释放总线,等待30us
DQ_IN;
}
static AWINLINE void am2301_temp3_delay(void)
{
timer_init(40);//40us后读取从机的低电平
}
static AWINLINE u8 am2301_temp4_read_lack(void)
{
u8 ack = !DQ_R;
if (ack) {
timer_init(80);//80us后读取从机的高电平
} else {
timer_init(50 * 1000); //ACK失败,100ms后测尝试
}
return ack;
}
static AWINLINE u8 am2301_temp5_read_hack(void)
{
u8 ack = DQ_R;
if (ack) {
timer_init(40 + AM2301_DATA_L_TIMER / 2); //65us后读取第一位数据信号的低电平时间
} else {
timer_init(50 * 1000); //ACK失败,100ms后测尝试
}
return ack;
}
static AWINLINE void am2301_temp6_first_bit_l(void)
{
#if USER_FUNC_INT_SRAM
timer_init(AM2301_DATA_L_TIMER / 2 + 26 + AM2301_DATA_L_TIMER / 2); //76us后读取第一位数据
#else
timer_init(AM2301_DATA_L_TIMER / 2 + 26 + AM2301_DATA_L_TIMER / 2 - 30); //函数放在flash需要减去30us
#endif
}
static FUNC_IN u8 am2301_init(void)
{
u8 ret;
if (temp_info.mode_type == TMP_INIT_OK) {
return TMP_INIT_OK;
}
temp_info.mode_type = (temp_info.mode_type == TMP_INIT_ACK) ? temp_info.mode_type : TMP_INIT_START;
switch (temp_info.mode_cnt) {
case 0:
am2301_temp0_reset();
break;
case 1:
am2301_temp1_reset_start();
break;
case 2:
am2301_temp2_release_bus();
break;
case 3:
am2301_temp3_delay();
break;
case 4:
ret = am2301_temp4_read_lack();
temp_info.mode_type = ret ? TMP_INIT_ACK : TMP_INIT_ERR;
if (!ret) {
temp_info.mode_cnt = 0;
if (++temp_info.sensor_check > SENSOR_CHECK_CNT) {
temp_info.sensor_type = SENSOR_ERR;
temp_info.sensor_check = 0;
}
return temp_info.mode_type;
}
break;
case 5:
ret = am2301_temp5_read_hack();
temp_info.mode_type = ret ? TMP_INIT_ACK : TMP_INIT_ERR;
if (!ret) {
temp_info.mode_cnt = 0;
if (++temp_info.sensor_check > SENSOR_CHECK_CNT) {
temp_info.sensor_type = SENSOR_ERR;
temp_info.sensor_check = 0;
}
return temp_info.mode_type;
}
break;
case 6:
am2301_temp6_first_bit_l();
temp_info.mode_type = TMP_INIT_OK;
temp_info.mode_cnt = 0;
temp_info.sensor_check = 0;
temp_info.sensor_type = SENSOR_AM2301;
return temp_info.mode_type;
break;
default:
break;
}
temp_info.mode_cnt++;
return temp_info.mode_type;
}
static AWINLINE u8 am2301_temp_read_bit(void)
{
u8 bit;
bit = DQ_R;
if (bit) {
timer_init(((AM2301_DATA1_H_TIMER - 26 - (AM2301_DATA_L_TIMER / 2)) + AM2301_DATA_L_TIMER / 2) + (AM2301_DATA_L_TIMER / 2 + 26 + AM2301_DATA_L_TIMER / 2) + ((temp_info.wr_bit) ? 1 : 0) + temp_info.wr_bit / 2); //((temp_info.wr_bit) ? 1 : 0) + temp_info.wr_bit / 2 属于补偿
} else {
timer_init(AM2301_DATA_L_TIMER / 2 + 26 + AM2301_DATA_L_TIMER / 2 + ((temp_info.wr_bit % 3 == 0) ? 1 : 0)); //((temp_info.wr_bit % 3 == 0) ? 1 : 0) 属于补偿
}
return bit;
}
static FUNC_IN u8 am2301_read_bytes(void)
{
if (temp_info.mode_type == TMP_READ_BYTE_OK) {
return TMP_READ_BYTE_OK;
}
if (!temp_info.byte_num && !temp_info.wr_bit) {
temp_info.read_data = 0;
}
temp_info.mode_type = TMP_READ_BYTE_START;
temp_info.read_data <<= 1;
temp_info.read_data |= am2301_temp_read_bit() ? 0x1 : 0x0;
temp_info.wr_bit++;
if (temp_info.wr_bit >= 8) {
temp_info.recv_data[temp_info.byte_num] = temp_info.read_data;
temp_info.read_data = 0;
temp_info.wr_bit = 0;
temp_info.byte_num++;
if (temp_info.byte_num >= 5) {
temp_info.byte_num = 0;
temp_info.mode_type = TMP_READ_BYTE_OK;
timer_init(50 * 1000);
}
}
return temp_info.mode_type;
}
u8 am2301_read(float *temp, float *humidity)//线程读取温度数据,temp_buf :温度数据存储地址
{
if (temp_info.read_step == STEP_AM_READ_DATA_OK) { //ds18b20温度读取正常
*temp = temp_info.ftemp;
*humidity = temp_info.fhumidity;
temp_info.read_step = STEP_AM_READ_REDO;//重新读取温度标记
return 1;
}
return 0;
}
/*****************************************************************************
AM2301中断处理函数
*****************************************************************************/
static FUNC_IN ___interrupt void am2301_timer_isr(void)
{
if (TMR->CON & BIT(15)) {
//读取温湿度步骤
switch (temp_info.read_step) {
case STEP_AM_SEND_INIT:
am2301_init();//1 . 初始化
break;
case STEP_AM_SEND_READ:
am2301_read_bytes();//2 . 读40字节
break;
case STEP_AM_READ_REDO:
temp_info.read_step = STEP_AM_SEND_INIT;
temp_mode_reinit();
temp_redo_next_time(3 * 1000 * 1000); //3S再次读取
break;
case STEP_AM_READ_DATA_OK:
;
u8 to_s = 10;//10s没有读取则重新读取
if (temp_info.ready_readed_tocnt > (((to_s * 1000) / 100) * 2)) { //10s重新读取
temp_info.ready_readed_tocnt = 0;
temp_info.read_step = STEP_AM_SEND_INIT;
temp_mode_reinit();
} else if (!temp_info.ready_readed_tocnt) {
temp_redo_next_time(100 * 1000); //100ms检测是否读取温度
}
temp_info.ready_readed_tocnt++;
break;
default:
break;
}
switch (temp_info.mode_type) {
case TMP_INIT_OK:
if (temp_info.read_step == STEP_AM_SEND_INIT) {
temp_info.read_step = STEP_AM_SEND_READ;
}
break;
case TMP_READ_BYTE_OK:
;
short hum = 0, tmp = 0, check_sum = 0, sum = 0;
hum = ((temp_info.recv_data[0] << 8) | temp_info.recv_data[1]) & 0xFFFF;
tmp = ((temp_info.recv_data[2] << 8) | temp_info.recv_data[3]) & 0xFFFF;
temp_info.ftemp = (float)tmp / 10;//温度
temp_info.fhumidity = (float)hum / 10;//湿度
sum = temp_info.recv_data[0] + temp_info.recv_data[1] + temp_info.recv_data[2] + temp_info.recv_data[3];
check_sum = temp_info.recv_data[4];
check_sum |= (sum > 255) ? (sum & 0xFF00) : 0;//数据校验,超255,高8位用sum的,传感器BUG
if (check_sum == sum) {
temp_info.read_step = STEP_AM_READ_DATA_OK;
} else {
temp_info.read_step = STEP_AM_READ_REDO;//重新读取温度标记
printf("AM3201 data check sum err\n");
}
temp_info.mode_type = TMP_NONE;
temp_info.ready_readed_tocnt = 0;
temp_info.recv_data[0] = temp_info.recv_data[1] = temp_info.recv_data[2] = temp_info.recv_data[3] = temp_info.recv_data[4] = 0;
temp_redo_next_time(100 * 1000); //100ms检测是否读取温度
break;
case TMP_ERR:
case TMP_INIT_ERR:
case TMP_WTITE_BYTE_ERR:
case TMP_READ_BYTE_ERR:
temp_info.read_step = STEP_AM_SEND_INIT;
temp_info.filter_cnt = 0;
temp_info.ftemp_rank_id = 0;
temp_mode_reinit();
temp_redo_next_time(50 * 1000); //100ms检测是否读取温度
break;
default :
break;
}
if (temp_info.timer_close) {
temp_info.timer_close = 0;
TMR->CON &= ~BIT(0);
}
TMR->CON |= BIT(14);
}
}
static void temp_app_task(void *priv)
{
u32 ret;
float temp;
float humidity;
temp_info.is_ds18b20 = TRUE;
os_time_dly(100);
while (1) {
if (temp_info.is_ds18b20) {
if (temp_info.sensor_type == SENSOR_ERR) {
os_time_dly(10);
}
ds18b20_io_init();
ds18b20_timer_init();
while (temp_info.sensor_type == SENSOR_NONE) {
os_time_dly(2);
}
if (temp_info.sensor_type == SENSOR_ERR) {
printf("DS18B20 check err\n\n");
ds18b20_timer_exit();
}
}
if (temp_info.sensor_type == SENSOR_DS1B820) {
while (1) {
ret = ds18b20_temp_read(&temp);//获取温度结果
if (ret) { //ds18b20温度读取正常
/*
做显示等......
*/
printf("---> DS18B20 : temp = %f \n", temp);
}
if (temp_info.sensor_type == SENSOR_ERR) {
ds18b20_timer_exit();
temp_info.is_ds18b20 = 0;
break;
}
os_time_dly(10); //延时100ms以上释放CPU
}
} else {
if (temp_info.sensor_type == SENSOR_ERR) {
os_time_dly(10);
}
am2301_io_init();
am2301_timer_init();
while (temp_info.sensor_type == SENSOR_NONE) {
os_time_dly(2);
}
if (temp_info.sensor_type == SENSOR_ERR) {
printf("AM3201 check err \n\n");
am2301_timer_exit();
}
while (1) {
ret = am2301_read(&temp, &humidity);//获取温度结果
if (ret) { //ds18b20温度读取正常
/*
做显示等......
*/
printf("---> AM3201 : temp = %f ,humidity = %f\n", temp, humidity);
}
if (temp_info.sensor_type == SENSOR_ERR) {
am2301_timer_exit();
temp_info.is_ds18b20 = TRUE;
break;
}
os_time_dly(00); //延时100ms以上释放CPU
}
}
}
}
static int temp_init(void *priv)
{
return os_task_create(temp_app_task, NULL, 16, 512, 0, "temp_app_task");
// return thread_fork("temp_app_task", 16, 512, 0, 0, temp_app_task, (void *)NULL);
}
late_initcall(temp_init);