AM2320单总线温湿度传感器使用AT32单片机中断读取及DMA读取的实现

本文聚焦AM2320单总线温湿度传感器常规驱动,因项目使用RTOS,模拟时序读取易失败,故介绍中断及DMA两种驱动方式。阐述了两种方式的实现思路,即通过下降沿触发记录数据,计算脉冲周期还原温湿度。还分析了各自优缺点,如中断受响应速度影响,DMA更稳定但可能冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AM2320单总线温湿度传感器常规驱动

AM2302,AM2320以及DHT22常规驱动都是采用IO引脚模拟时序读出的方式实现的。AM2320还可以使用I2C驱动,本文主要介绍单总线方式。

背景

目前的项目中,由于使用了RTOS,致模拟时序的方式会被其他线程或中断打断,导致读取失败,虽然偶尔失败一两次,不影响后续温湿度结果,同时也可以使用禁用调度或中断的方式来保证单总线的读取时序,但项目使用的AT32F437单片机,性能强劲,应该有更好的实现方式。下面将介绍中断DMA两种驱动的实现方式。

AM2320时序

AM2320单总线时序

中断驱动方式

实现思路

通过从机发送数据的下降沿来触发外部中断,中断里面记录当前的SysTick->VAL,一共41次下降沿完成数据传输,第一次下降沿为从机的响应的结束时刻,后续为数据。根据两次中断的间隔计算出脉冲的周期,判断是0或1。

  1. 主机发送完起始信号后,使用单总线的IO口来触发中断,下降沿一次,进入中断一次,在中断里面记录当前的SysTick->VAL
  2. 一共需传输41次,根据记录到的数值,计算脉冲周期并还原出温湿度数据。
  3. 具体实现关键代码如下:

/**
 * 函数功能: 使AM2302-DATA引脚变为上拉输入模式
 * 输入参数: 无
 * 返 回 值: 无
 * 说    明:无
 */
static void AM2302_Mode_IPU(void)
{
   
   
    gpio_init_type gpio_init_struct;

    gpio_default_para_init(&gpio_init_struct);
    gpio_init_struct.gpio_pins = AM2302_Dout_PIN;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(AM2302_Dout_PORT, &gpio_init_struct);
}

/**
 * 函数功能: 使AM2302-DATA引脚变为开漏输出模式
 * 输入参数: 无
 * 返 回 值: 无
 * 说    明:无
 */
static void AM2302_Mode_Out_OD(void)
{
   
   
    gpio_init_type gpio_init_struct;

    gpio_default_para_init(&gpio_init_struct);
    gpio_init_struct.gpio_pins = AM2302_Dout_PIN;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(AM2302_Dout_PORT, &gpio_init_struct);
}
// 一共下降沿41次,中断41次
#define FALLING_CNT (41)
__IO static uint8_t isr_nums = 0;
// 读出结果
__IO static uint8_t result[5] = {
   
   0};
// 读出结果
__IO static uint8_t us_result[FALLING_CNT] = {
   
   0};
// 暂存定时器计数值
__IO uint32_t dst_buffer[FALLING_CNT] = {
   
   0};
static void result_reset(void)
{
   
   
    rt_memset(result, 0, 5);
    rt_memset(us_result, 0, FALLING_CNT);
    rt_memset(dst_buffer, 0, FALLING_CNT * sizeof(uint32_t));
    isr_nums = 0;
}
/**
 * 函数功能: AM2302数据引脚中断函数,记录SysTick->VAL
 * 输入参数: 无
 * 返 回 值: 无
 * 说    明:无
 */
static uint8_t AM2302_Read_Isr(void)
{
   
   
    dst_buffer[isr_nums++] = SysTick->VAL;
}
void printf_bin_8(unsigned char num)
{
   
   
    int k;
    unsigned char *p = (unsigned char *)#

    for (int k = 7; k >= 0; k--) // 处理8个位
    {
   
   
        if (*p & (1 << k))
            rt_kprintf("1");
        else
            rt_kprintf("0");
    }
    rt_kprintf("\r\n");
}
/**
 * 函数功能: 一次完整的数据传输为40bit,高位先出
 * 输入参数: AM2302_Data:AM2302数据类型
 * 返 回 值: ERROR:  读取出错
 *           SUCCESS:读取成功
 * 说    明:8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
 */
uint8_t AM2302_Read_TempAndHumidity(AM2302_Data_TypeDef *AM2302_Data)
{
   
   
    uint8_t temp;
    uint16_t humi_temp;
    uint16_t cnt = 0;
    uint8_t humi_high8bit; // 原始数据:湿度高8位
    uint8_t humi_low8bit;  // 原始数据:湿度低8位
    uint8_t temp_high8bit; // 原始数据:温度高8位
    uint8_t temp_low8bit;  // 原始数据:温度高8位
    uint8_t check_sum;     // 校验和
    /*输出模式*/
    AM2302_Mode_Out_OD();
    /*主机拉低*/
    AM2302_Dout_LOW();
    /*延时2ms*/
    rt_thread_mdelay(2);

    /*总线拉高 主机延时30us*/
    AM2302_Dout_HIGH();
    rt_hw_us_delay(30); // 延时30us
    /*主机设为输入 判断从机响应信号*/
    AM2302_Mode_IPU();
    /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/
    if (AM2302_Data_IN() == FALSE)
    {
   
   
        result_reset();
        // rt_kprintf("%d",get_system_us()-us_tick);

        /* 绑定中断,下降沿模式,回调函数名为PowOff_Isr */
        rt_pin_attach_irq(AM2302_Data_IN_PIN, PIN_IRQ_MODE_FALLING, AM2302_Read_Isr, RT_NULL);
        /* 使能中断 */
        rt_pin_irq_enable(AM2302_Data_IN_PIN, PIN_IRQ_ENABLE);
    }
    else
    {
   
   
        return ERROR;
    }

    cnt = 0;
    do
    {
   
   
        rt_thread_mdelay(2);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值