首先说一下,我做的是模拟的IIC进行数据的读取,所以相对比较简单,时钟按照芯片主频稍作修改即可,我们目前使用的是PB9作为SCL引脚,PB8作为SDA引脚,整个连接如下图

00-连接图.png
完成了引脚的连接,那么我们就来修改AHT11的代码,这里直接上代码
  1. #include "DRV_AHT10.h"

  2. float TempData=0,WetData=0;


  3. void Delay_N10us(uint32_t t)//延时函数
  4. {
  5.   uint32_t k;

  6.    while(t--)
  7.   {
  8.      for (k = 0; k < 719; k++)//110
  9.       ;
  10.   }
  11. }



  12. void SensorDelay_us(uint32_t t)//延时函数
  13. {
  14.         t = t-2;       
  15.         for(; t>0; t--)
  16.         {
  17.                 Delay_N10us(1);
  18.         }

  19. }

  20. void Delay_3us(void)                //延时函数
  21. {       
  22.         Delay_N10us(1);
  23.         Delay_N10us(1);
  24.         Delay_N10us(1);
  25.         Delay_N10us(1);
  26. }
  27. void Delay_1us(void)                //延时函数
  28. {       
  29.         Delay_N10us(1);
  30.         Delay_N10us(1);
  31.         Delay_N10us(1);
  32.         Delay_N10us(1);
  33.         Delay_N10us(1);

  34. }
  35. //--SCL_PA00---SDA-PA01---

  36. void SDA_Pin_Output_High(void)   //将P15配置为输出 , 并设置为高电平, P15作为I2C的SDA
  37. {
  38.   GPIO_Pins_Set(GPIOB,GPIO_PIN_8);
  39. }

  40. void SDA_Pin_Output_Low(void)  //将P15配置为输出  并设置为低电平
  41. {
  42.   GPIO_Pins_Reset(GPIOB,GPIO_PIN_8);
  43. }



  44. void SDA_Pin_IN_FLOATING(void)  //SDA配置为悬浮输入
  45. {
  46.        
  47.        
  48.           GPIO_InitType GPIO_InitStructure;
  49.                 RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
  50.           //PA1-PA7-PA9
  51.                 GPIO_InitStructure.Pin          = GPIO_PIN_8;
  52.                 GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_INPUT;
  53.                 GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
  54.                 GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
  55.        
  56.        
  57.        
  58. }

  59. void SDA_Pin_OUT_PP(void)  //SDA配置为悬浮输入
  60. {
  61.           GPIO_InitType GPIO_InitStructure;
  62.                 RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
  63.           //PA1-PA7-PA9
  64.                 GPIO_InitStructure.Pin          = GPIO_PIN_8;
  65.                 GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_OUT_PP;
  66.                 GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
  67.                 GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
  68. }



  69. void SCL_Pin_Output_High(void) //SCL输出高电平,P14作为I2C的SCL
  70. {
  71.     GPIO_Pins_Set(GPIOB,GPIO_PIN_9);
  72. }

  73. void SCL_Pin_Output_Low(void) //SCL输出低电平
  74. {
  75. GPIO_Pins_Reset(GPIOB,GPIO_PIN_9);
  76. }

  77. void Init_I2C_Sensor_Port(void) //初始化I2C接口
  78. {       
  79.        
  80.                   GPIO_InitType GPIO_InitStructure;
  81.                 RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
  82.           //--SDA_PB8
  83.                 GPIO_InitStructure.Pin          = GPIO_PIN_8;
  84.                 GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_OUT_PP;
  85.                 GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
  86.                 GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
  87.                
  88.                 RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
  89.           //SCL_PB9
  90.                 GPIO_InitStructure.Pin          = GPIO_PIN_9;
  91.                 GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_OUT_PP;
  92.                 GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
  93.                 GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
  94.                
  95.                
  96. }


  97. void I2C_Start(void)                 //I2C主机发送START信号
  98. {
  99. SDA_Pin_Output_High();
  100. SensorDelay_us(8);
  101. SCL_Pin_Output_High();
  102. SensorDelay_us(8);
  103. SDA_Pin_Output_Low();
  104. SensorDelay_us(8);
  105. SCL_Pin_Output_Low();
  106. SensorDelay_us(8);   
  107. }


  108. void ZSSC_I2C_WR_Byte(uint8_t Byte) //往AHT10写一个字节
  109. {
  110.         uint8_t Data,N,i;       
  111.         SDA_Pin_OUT_PP();
  112.         Data=Byte;
  113.         i = 0x80;
  114.         for(N=0;N<8;N++)
  115.         {
  116.                 SCL_Pin_Output_Low();
  117.           
  118.                 Delay_3us();       
  119.                
  120.                 if(i&Data)
  121.                 {
  122.                         SDA_Pin_Output_High();
  123.                 }
  124.                 else
  125.                 {
  126.                         SDA_Pin_Output_Low();
  127.                 }       
  128.                        
  129.         SCL_Pin_Output_High();
  130.                 Delay_3us();
  131.                
  132.                 Data <<= 1;
  133.                  
  134.         }
  135.         SCL_Pin_Output_Low();
  136.         SensorDelay_us(8);   
  137.         SDA_Pin_IN_FLOATING();
  138.         SensorDelay_us(8);       
  139. }       


  140. uint8_t ZSSC_I2C_RD_Byte(void)//从AHT10读取一个字节
  141. {
  142.         uint8_t Byte,i,a;
  143.         Byte = 0;
  144.         SCL_Pin_Output_Low();
  145.         SDA_Pin_IN_FLOATING();
  146.         SensorDelay_us(8);       
  147.         for(i=0;i<8;i++)
  148.         {
  149.     SCL_Pin_Output_High();               
  150.                 Delay_1us();
  151.                 a=0;
  152.                 if(GPIO_Input_Pin_Data_Get(GPIOB,GPIO_PIN_8)==PIN_SET)//--读取引脚状态
  153.                 {
  154.                         a=1;
  155.                 }

  156.                 Byte = (Byte<<1)|a;
  157.                 SCL_Pin_Output_Low();
  158.                 Delay_1us();
  159.         }
  160.     SDA_Pin_IN_FLOATING();
  161.         SensorDelay_us(8);       
  162.         return Byte;
  163. }


  164. uint8_t Receive_ACK(void)   //看AHT10是否有回复ACK
  165. {
  166.         uint16_t CNT;
  167.         CNT = 0;
  168.         SCL_Pin_Output_Low();       
  169.         SDA_Pin_IN_FLOATING();
  170.         SensorDelay_us(8);       
  171.         SCL_Pin_Output_High();       
  172.         SensorDelay_us(8);       
  173.         while((GPIO_Input_Pin_Data_Get(GPIOB,GPIO_PIN_8)==PIN_SET)        && CNT < 100)
  174.         {
  175.                 CNT++;
  176.         }               

  177.         if(CNT == 100)
  178.         {
  179.                 return 0;
  180.         }
  181.         SCL_Pin_Output_Low();       
  182.         SensorDelay_us(8);       
  183.         return 1;
  184. }

  185. void Send_ACK(void)                  //主机回复ACK信号
  186. {
  187.        
  188.         SDA_Pin_OUT_PP();
  189.         SCL_Pin_Output_Low();       
  190.         SensorDelay_us(8);       
  191.         SDA_Pin_Output_Low();
  192.         SensorDelay_us(8);       
  193.         SCL_Pin_Output_High();       
  194.         SensorDelay_us(8);
  195.         SCL_Pin_Output_Low();       
  196.         SensorDelay_us(8);
  197.         SDA_Pin_IN_FLOATING();
  198.         SensorDelay_us(8);
  199. }

  200. void Send_NOT_ACK(void)        //主机不回复ACK
  201. {
  202.         SDA_Pin_OUT_PP();
  203.         SCL_Pin_Output_Low();       
  204.         SensorDelay_us(8);
  205.         SDA_Pin_Output_High();
  206.         SensorDelay_us(8);
  207.         SCL_Pin_Output_High();       
  208.         SensorDelay_us(8);               
  209.         SCL_Pin_Output_Low();       
  210.         SensorDelay_us(8);
  211.     SDA_Pin_Output_Low();
  212.         SensorDelay_us(8);
  213. }

  214. void Stop_I2C(void)          //一条协议结束
  215. {
  216.         SDA_Pin_OUT_PP();
  217.         SDA_Pin_Output_Low();
  218.         SensorDelay_us(8);
  219.         SCL_Pin_Output_High();       
  220.         SensorDelay_us(8);
  221.         SDA_Pin_Output_High();
  222.         SensorDelay_us(8);
  223. }

  224. uint8_t JH_Read_Status(void)//读取AHT10的状态寄存器
  225. {

  226.         uint8_t Byte_first;       
  227.         I2C_Start();
  228.         ZSSC_I2C_WR_Byte(0x71);
  229.         Receive_ACK();
  230.         Byte_first = ZSSC_I2C_RD_Byte();
  231.                

  232.         Send_NOT_ACK();
  233.         Stop_I2C();


  234.         return Byte_first;
  235. }

  236. uint8_t JH_Read_Cal_Enable(void)  //查询cal enable位有没有使能?
  237. {
  238.         uint8_t val = 0;//ret = 0,

  239.   val = JH_Read_Status();
  240.   if((val & 0x68)==0x08)  //判断NOR模式和校准输出是否有效
  241.   return 1;
  242.   else  return 0;
  243. }



  244. void JH_SendAC(void) //向AHT10发送AC命令
  245. {

  246. I2C_Start();
  247. ZSSC_I2C_WR_Byte(0x70);
  248. Receive_ACK();
  249. ZSSC_I2C_WR_Byte(0xac);
  250. Receive_ACK();
  251. ZSSC_I2C_WR_Byte(0x33);
  252. Receive_ACK();
  253. ZSSC_I2C_WR_Byte(0x00);
  254. Receive_ACK();
  255. Stop_I2C();

  256. }

  257. void JH_Send_BA(void)//向AHT10发送BA命令
  258. {


  259. I2C_Start();
  260. ZSSC_I2C_WR_Byte(0x70);
  261. Receive_ACK();
  262. ZSSC_I2C_WR_Byte(0xba);
  263. Receive_ACK();
  264. Stop_I2C();


  265. }

  266. void JH_Read_CTdata(uint32_t *ct) //读取AHT10的温度和湿度数据
  267. {
  268.         volatile uint8_t  Byte_1th=0;
  269.         volatile uint8_t  Byte_2th=0;
  270.         volatile uint8_t  Byte_3th=0;
  271.         volatile uint8_t  Byte_4th=0;
  272.         volatile uint8_t  Byte_5th=0;
  273.         volatile uint8_t  Byte_6th=0;
  274.          uint32_t RetuData = 0;
  275.        
  276.         uint16_t cnt = 0;


  277.         JH_SendAC();//向AHT10发送AC命令

  278.          SysTick_Delay_Ms(75);//等待75ms
  279.     cnt = 0;
  280.         while(((JH_Read_Status()&0x80)==0x80))//等待忙状态结束
  281.         {
  282.          SensorDelay_us(1508);
  283.          if(cnt++>=100)
  284.          {
  285.           break;
  286.           }
  287.         }
  288.         I2C_Start();

  289.         ZSSC_I2C_WR_Byte(0x71);//0x70+1   0x70为设备地址 1为方向位
  290.         Receive_ACK();
  291.         Byte_1th = ZSSC_I2C_RD_Byte();//状态字
  292.         Send_ACK();
  293.         Byte_2th = ZSSC_I2C_RD_Byte();//湿度字节
  294.         Send_ACK();
  295.         Byte_3th = ZSSC_I2C_RD_Byte();//湿度字节
  296.         Send_ACK();
  297.         Byte_4th = ZSSC_I2C_RD_Byte();//高4位为湿度  低4位为温度
  298.         Send_ACK();
  299.         Byte_5th = ZSSC_I2C_RD_Byte();//温度字节
  300.         Send_ACK();
  301.         Byte_6th = ZSSC_I2C_RD_Byte();//温度字节
  302.         Send_NOT_ACK();
  303.         Stop_I2C();

  304.         RetuData = (RetuData|Byte_2th)<<8;
  305.         RetuData = (RetuData|Byte_3th)<<8;
  306.         RetuData = (RetuData|Byte_4th);
  307.         RetuData =RetuData >>4;
  308.         ct[0] = RetuData;
  309.         RetuData = 0;
  310.         RetuData = (RetuData|Byte_4th)<<8;
  311.         RetuData = (RetuData|Byte_5th)<<8;
  312.         RetuData = (RetuData|Byte_6th);
  313.         RetuData = RetuData&0xfffff;
  314.         ct[1] =RetuData;

  315. }


  316. unsigned  char  JH_Init(void)   //初始化AHT10
  317. {

  318.         unsigned int count=0;
  319.         Init_I2C_Sensor_Port();
  320.         SensorDelay_us(11038);

  321.         I2C_Start();
  322.         ZSSC_I2C_WR_Byte(0x70);
  323.         Receive_ACK();
  324.         ZSSC_I2C_WR_Byte(0xe1);//写系统配置寄存器
  325.         Receive_ACK();
  326.         ZSSC_I2C_WR_Byte(0x08);
  327.         Receive_ACK();
  328.         ZSSC_I2C_WR_Byte(0x00);
  329.         Receive_ACK();
  330.         Stop_I2C();

  331.         SysTick_Delay_Ms(500);//延时0.5S
  332.    while(JH_Read_Cal_Enable()==0)//需要等待状态字status的Bit[3]=1时才去读数据。如果Bit[3]不等于1 ,发软件复位0xBA给AHT10,再重新初始化AHT10,直至Bit[3]=1
  333.    {
  334.    
  335.                                 JH_Send_BA();  //复位
  336.                                 SysTick_Delay_Ms(100);
  337.                                 SensorDelay_us(11038);

  338.                                 I2C_Start();
  339.                                 ZSSC_I2C_WR_Byte(0x70);
  340.                                 Receive_ACK();
  341.                                 ZSSC_I2C_WR_Byte(0xe1);//写系统配置寄存器
  342.                                 Receive_ACK();
  343.                                 ZSSC_I2C_WR_Byte(0x08);
  344.                                 Receive_ACK();
  345.                                 ZSSC_I2C_WR_Byte(0x00);
  346.                                 Receive_ACK();
  347.                                 Stop_I2C();
  348.                                 count++;
  349.                                 if(count>=10)
  350.                                         return 0;
  351.                                 SysTick_Delay_Ms(500);
  352.     }
  353.    return 1;
  354. }



  355. void Get_Data(void)
  356. {
  357.     uint32_t CT_data[2];
  358.                 volatile int  c1,t1;

  359.          
  360.                 if(0)
  361.                 {


  362.                 }
  363.                 else
  364.                 {
  365.                        
  366.                                 while(JH_Read_Cal_Enable()==0)//等到校准输出使能位为1,才读取。
  367.                                 {
  368.                                         JH_Init();//如果为0再使能一次
  369.                                         SysTick_Delay_Ms(50);
  370.                                 }
  371.                                 JH_Read_CTdata(CT_data);  //读取温度和湿度 , 可间隔1.5S读一次
  372.                                 c1 = CT_data[0]*1000/1024/1024;  //计算得到湿度值(放大了10倍,如果c1=523,表示现在湿度为52.3%)
  373.                                 t1 = CT_data[1] *200*10/1024/1024-500;//计算得到温度值(放大了10倍,如果t1=245,表示现在温度为24.5℃)
  374.                                 TempData=t1*0.1;//因为设置了两位小数--
  375.                                 WetData=c1*0.1;//--放大了两倍----
  376.                 }

  377. }



这里就只上传传感器的代码,然后是MAIN函数的代码,非常的简单

  1. #include "n32g401.h"
  2. #include "bsp_delay.h"
  3. #include "DRV_UART.h"
  4. #include "DRV_TIM.h"
  5. #include "DRV_AHT10.h"


  6. int main(void)
  7.                           {
  8.         LED_Init();
  9.         UART_Init();
  10.         TIM_Init();
  11.         JH_Init();   //初始化AHT10;
  12.         while(1)
  13.         {
  14.                 Get_Data();
  15.                 printf("TempData is %2f3 %\r\n",TempData);
  16.                 printf("WetData  is %2f3 %\r\n",WetData);
  17.                 SysTick_Delay_Ms(500);
  18.                
  19.         }
  20. }


好了,我们来看看实时的结果:
串口结果.png
测试结果还是比较准确的,我拍了视频,后面上传上来,主要是在办公室,不太好说话,所以大家感受一下结果就行了,感兴趣的话可以自己复制代码去测试。

视频链接:
https://www.bilibili.com/video/BV1AusjeuEL7/?buvid=XU268A1260BC1080F6C5DE9BB8885853A284E&is_story_h5=false&mid=ZPNijV8XOdBxHvi4hyDZnQ%3D%3D&plat_id=240&share_from=ugc&share_medium=android&share_plat=android&share_session_id=34ec3807-b268-440c-a310-66412bf9f865&share_source=WEIXIN&share_tag=s_i&spmid=dt.space-dt.0.0×tamp=1724649027&unique_k=HwCthPZ&up_id=474849000