驱动DHT11单总线温湿度传感器的方式与内核驱动GPIO读写的方式基本无差异,都是通过对/dev目录下的设备文件进行write/read操作,不同的是DHT11的读取需要不断切换GPIO输入输出状态并不断做轮询,其运行层面是驱动层,对于系统来说,驱动层代码的实时性要求和读写优先级都要高于应用层代码,即要将更多的CPU任务时间片资源放到驱动层代码中,也就只有这样,才能对DHT11这种延时响应时间要求是微秒级的单总线器件进行正常读写。废话不多说放上DHT11的驱动源码,这份代码参考了一位开发驱动的朋友@jackeyt,修改了一些小地方:
  1. #include <linux/err.h>
  2. #include <linux/gpio.h>
  3. #include <linux/of_gpio.h>
  4. #include <linux/gpio/consumer.h>
  5. #include <linux/kernel.h>
  6. #include <linux/module.h>
  7. #include <linux/of.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/property.h>
  10. #include <linux/slab.h>
  11. #include <linux/fs.h>
  12. #include <linux/types.h>
  13. #include <linux/delay.h>
  14. #include <linux/device.h>
  15. #include <asm/uaccess.h>
  16. static int dht11_major = 0;
  17. static int dht11_gpio=80;
  18. static struct class *dht11_class;//类
  19. static struct device *dht11_dev;//设备
  20. static const char* dht11_name = "dht11";
  21. typedef struct        DHT11_SENSOR_DATA
  22. {
  23.         u16 temp;//温度
  24.         u16 hum;//湿度
  25. }dht11_data;
  26. #define DHT11_DQ_High    gpio_direction_output(dht11_gpio, 1)
  27. #define DHT11_DQ_Low     gpio_direction_output(dht11_gpio, 0)
  28. #define DHT11_IO_IN                 gpio_direction_input(dht11_gpio)
  29. #define delay_us(x)                udelay(x)
  30. #define delay_ms(x)                msleep(x)
  31. static u8 DHT11_Read_DQ(void)   
  32. {
  33.         DHT11_IO_IN;
  34.         return gpio_get_value(dht11_gpio);
  35. }
  36. //复位DHT11
  37. static void DHT11_Rst(void)   
  38. {                 
  39.         DHT11_DQ_Low;
  40.         msleep (20);  //拉低至少18ms
  41.         DHT11_DQ_High; //DQ=1
  42.         delay_us (30);  //主机拉高20~40us
  43. }
  44. //等待DHT11的回应
  45. //返回1:未检测到DHT11的存在
  46. //返回0:存在
  47. static u8 DHT11_Check(void)   
  48. {   
  49.         u8 retry=0;//定义临时变量
  50.         DHT11_IO_IN;//SET INPUT
  51.         while ((DHT11_Read_DQ()==1)&&retry<100)//DHT11会拉低40~80us
  52.         {
  53.                 retry++;
  54.                 delay_us(1);
  55.         };
  56.         if(retry>=100)return 1;
  57.         else retry=0;
  58.         while ((DHT11_Read_DQ()==0)&&retry<100)//DHT11拉低后会再次拉高40~80us
  59.         {
  60.                 retry++;
  61.                 delay_us(1);
  62.         };
  63.         if(retry>=100)return 1;   
  64.         return 0;
  65. }
  66. //从DHT11读取一个位
  67. //返回值:1/0
  68. static u8 DHT11_Read_Bit(void)  
  69. {
  70.         u8 retry=0;
  71.         while((DHT11_Read_DQ()==1)&&retry<100)//等待变为低电平
  72.         {
  73.                 retry++;
  74.                 delay_us(1);
  75.         }
  76.         retry=0;
  77.         while((DHT11_Read_DQ()==0)&&retry<100)//等待变高电平
  78.         {
  79.                 retry++;
  80.                 delay_us(1);
  81.         }
  82.         delay_us(40);//等待40us
  83.         if(DHT11_Read_DQ()==1)
  84.         return 1;
  85.         else
  86.         return 0;   
  87. }
  88. //从DHT11读取一个字节
  89. //返回值:读到的数据
  90. static u8 DHT11_Read_Byte(void)   
  91. {        
  92.     u8 i,dat;
  93.     dat=0;
  94.         for (i=0;i<8;i++)
  95.         {
  96.                 dat<<=1;
  97.                 dat|=DHT11_Read_Bit();
  98.         }   
  99.         return dat;
  100. }
  101. //从DHT11读取一次数据
  102. //temp:温度值(范围:0~50°)
  103. //humi:湿度值(范围:20%~90%)
  104. //返回值:0,正常;1,读取失败
  105. static u8 DHT11_Read_Data(u16 *temp,u16 *humi)   
  106. {        
  107.         u8 buf[5];
  108.         u8 i;
  109.         DHT11_Rst();
  110.         if(DHT11_Check()==0)
  111.         {
  112.                 for(i=0;i<5;i++)//读取40位数据
  113.                 {
  114.                         buf[i]=DHT11_Read_Byte();
  115.                 }
  116.                 if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
  117.                 {
  118.                         *humi=buf[0]<<8|buf[1];
  119.                         *temp=buf[2]<<8|buf[3];
  120.                         printk("buf=%d,%d,%d,%d,%d\n",buf[0],buf[1],buf[2],buf[3],buf[4]);
  121.                 }
  122.         }else return 1;
  123.         return 0;   
  124. }
  125. //初始化DHT11的IO口 DQ 同时检测DHT11的存在
  126. //返回1:不存在
  127. //返回0:存在     
  128. static void DHT11_Init(void)
  129. {     
  130.         DHT11_Rst();  //复位DHT11
  131.         DHT11_Check();//等待DHT11的回应
  132. }
  133. int DHT11_open(struct inode *inode, struct file *flips)
  134. {
  135.         printk("--------------%s--------------\n",__FUNCTION__);
  136.         return 0;
  137. }
  138. static ssize_t DHT11_read(struct file *file, char __user *buf,
  139.                     size_t nbytes, loff_t *ppos)
  140. {       
  141.         printk("--------------%s--------------\n",__FUNCTION__);
  142.        
  143.         dht11_data Last_dht11_data;
  144.         if(DHT11_Read_Data(&Last_dht11_data.temp,&Last_dht11_data.hum) == 0)//读取温湿度值
  145.         {
  146.                 if (raw_copy_to_user(buf,&Last_dht11_data,sizeof(Last_dht11_data)) )
  147.                 {
  148.                         return EFAULT ;
  149.                 }
  150.         }
  151. }
  152. static int DHT11_close(struct inode *inode, struct file *flip)
  153. {
  154.         printk("--------------%s--------------\n",__FUNCTION__);
  155.         return 0;
  156. }
  157. static struct file_operations dht11_fops = {
  158.         .owner = THIS_MODULE,
  159.         .read = DHT11_read,
  160.         .open = DHT11_open,
  161.         .release = DHT11_close,
  162. };
  163. static const struct of_device_id of_dht11_match[] = {
  164.         { .compatible = "dht11", },
  165.         {},
  166. };
  167. MODULE_DEVICE_TABLE(of, of_dht11_match);
  168. static int dht11_probe(struct platform_device *pdev)
  169. {
  170.         int ret;  
  171.         enum of_gpio_flags flag;//(flag == OF_GPIO_ACTIVE_LOW) ?
  172.         printk("-------%s-------------\n", __FUNCTION__);
  173.        
  174.     struct device_node *dht11_gpio_node = pdev->dev.of_node;
  175.        
  176.         //dht11_gpio = of_get_named_gpio_flags(dht11_gpio_node->child, "gpios", 0, &flag);
  177.         if (!gpio_is_valid(dht11_gpio))
  178.         {
  179.             printk("dht11-gpio: %d is invalid\n", dht11_gpio);
  180.                 return -ENODEV;
  181.     }
  182.         else
  183.                 printk("dht11-gpio: %d is valid!\n", dht11_gpio);
  184.         if (gpio_request(dht11_gpio, "dht11-gpio"))
  185.         {
  186.         printk("gpio %d request failed!\n", dht11_gpio);
  187.         gpio_free(dht11_gpio);
  188.         return -ENODEV;
  189.     }
  190.         else
  191.                 printk("gpio %d request success!\n", dht11_gpio);
  192.         //能够读到配置信息之后就可以开始创建设备节点
  193.         dht11_major = register_chrdev(0, "dht11",&dht11_fops);
  194.         if(dht11_major <0)
  195.         {
  196.                 printk(KERN_ERR "reg error!\n");
  197.                 goto err_0;               
  198.         }
  199.         else
  200.                 printk("dht11_major =%d\n",dht11_major);
  201.        
  202.         dht11_class = class_create(THIS_MODULE,"dht11_class");//creat class
  203.         if( IS_ERR(dht11_class))
  204.         {
  205.                 printk(KERN_ERR "fail create class\n");
  206.                 ret = PTR_ERR(dht11_class);
  207.                 goto err_1;
  208.         }
  209.        
  210.         //creat dht11_dev--->>/dev/dht11_dev
  211.         dht11_dev = device_create(dht11_class, NULL,MKDEV(dht11_major,0), NULL, dht11_name);
  212.         if(IS_ERR(dht11_dev))
  213.         {
  214.                 printk(KERN_ERR "fail create device!\n");
  215.                 ret = PTR_ERR(dht11_dev);
  216.                 goto err_2;               
  217.         }
  218.        
  219.         //init dht11
  220.         DHT11_Init();
  221.         printk("dht11 Initing...\n");
  222.         return 0;
  223.        
  224. err_2:
  225.                 device_destroy(dht11_class,MKDEV(dht11_major,0));
  226. err_1:
  227.                 class_destroy(dht11_class);
  228. err_0:
  229.                 unregister_chrdev(dht11_major,dht11_name);       
  230.                 return -1;
  231. }
  232. static int dht11_remove(struct platform_device *pdev)
  233. {
  234.         printk("-------%s-------------\n", __FUNCTION__);
  235.         device_destroy(dht11_class,MKDEV(dht11_major,0));
  236.         class_destroy(dht11_class);
  237.         unregister_chrdev(dht11_major,dht11_name);
  238.         return 0;
  239. }
  240. static void dht11_shutdown(struct platform_device *pdev)
  241. {
  242.         printk("-------%s-------------\n", __FUNCTION__);
  243. }
  244. static struct platform_driver dht11_driver = {
  245.         .probe                = dht11_probe,
  246.         .remove                = dht11_remove,
  247.         .shutdown        = dht11_shutdown,
  248.         .driver                = {
  249.                 .name        = "dht11_driver",
  250.                 .of_match_table = of_dht11_match,
  251.         },
  252. };
  253. module_platform_driver(dht11_driver);


首先是GPIO引脚确定的方式,我将朋友的通过设备树锁定的方式改为在驱动代码里面动态分配,通过宏定义进行指定,不在设备树里面锁定任何GPIO;然后是里面的printk打印会出现在串口终端中,不管串口终端有没有在执行别的进程;对于内核源码中的udelay() msleep() gpio_direction_output() gpio_get_value()等函数则与ARM的单片机用法基本一样,可以完美兼容,唯一的不同点就是应用层代码对/dev设备进行wirte/read的时机和方式有要求。
然后是makefile代码,这个直接套用模板即可,内核源码目录用回之前的/mnt/imx8maaxksrc:
编译完成之后,需要使用
  1. insmod dht11_drv.ko
命令进行驱动插入:
20.jpg

可以看到,DHT11驱动源码中的dht11_probe函数加入的printk打印在插入的时候就已经生效了。
然后是单独对DHT11器件进行简单读写的main函数:
这里我注意到一点,对于/dev/dht11设备,读取间隔是1秒1次,不管是在主线程(main())中还是在新开辟的线程中,都必须要有这个间隔,不然读取会失败,一般对于DHT11这种轮询器件而言,都是有必要开启一个单独线程进行读取的,比较Linux中线程资源非常充足,而DHT11对于实时性要求又比较高。
然后我这边套用一套以前自己写的HTTP网页服务器代码,非常简单,是通过TCP方式进行GET/POST操作,简单得不能再简单那种:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4. #include <stdint.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <fcntl.h>
  8. #include <time.h>
  9. #include <unistd.h>
  10. #include <string.h>
  11. #include <fcntl.h>
  12. #include <unistd.h>
  13. #include <pthread.h>
  14. #include <linux/input.h>
  15. #include <sys/mman.h>
  16. #include <sys/socket.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <arpa/inet.h>
  20. #include <netinet/in.h>
  21. #define RUN  1
  22. #define STOP 0
  23. pthread_t id1,id2;
  24. int fd_socket_server,fd_socket_conn;
  25. pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
  26. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  27. char sendbuf[420],recvbuf[1000];
  28. int thread_flag=0,status=STOP;
  29. #define TEMP_PATH "/sys/class/thermal/thermal_zone0/temp"
  30. #define DHT11_PATH "/dev/dht11"
  31. typedef struct
  32. {
  33.         short temp;
  34.         short humi;
  35. }dht11_data;
  36. dht11_data dht11_data1;
  37. int fd_dht11;
  38. float dht11_temp,dht11_humi;
  39. void *Thread_CPU_Temp(void *arg)
  40. {
  41.     void *ret;
  42.     int fd,retval;
  43.     float temp=0;
  44.     char buf[30];
  45.         while(1)
  46.         {
  47.                 read( fd_dht11 , &dht11_data1 , sizeof(dht11_data1));
  48.                 if(dht11_data1.temp != 0xffff)
  49.                 {
  50.                         dht11_temp = (dht11_data1.temp>>8)*1.0 + (dht11_data1.temp&0xff)*0.1;
  51.                         dht11_humi = (dht11_data1.humi>>8)*1.0 + (dht11_data1.humi&0xff)*0.1;
  52.                 }
  53.                 sleep(1);
  54.         }
  55.     while(1)
  56.     {
  57.                 //                pthread_mutex_lock(&mut);
  58.                 //                  while(!status)
  59.                 //                  {
  60.                 //                          pthread_cond_wait(&cond, &mut);
  61.                 //                  }
  62.                 //                  pthread_mutex_unlock(&mut);
  63.         fd = open(TEMP_PATH, O_RDONLY);
  64.         if (fd<0)
  65.         {
  66.             fprintf(stderr,"无法打开thermal_zone0/temp文件\n");
  67.             return ret;
  68.         }
  69.         if (read(fd,buf,30)<0)
  70.         {
  71.             fprintf(stderr,"读取温度数据失败\n");
  72.             return ret;
  73.         }
  74.         temp = atoi(buf)/1000.0;
  75.         printf("CPU温度��?.1f\n",temp);
  76.         buf[0]=(int)temp/10%10+'0';
  77.         buf[1]=(int)temp%10+'0';
  78.         buf[2]='.';
  79.         buf[3]=(int)(temp*10)%10+'0';
  80.         buf[4]=0;
  81.         send(fd_socket_conn,buf,5,0);
  82.         sleep(1);
  83.     }
  84. }
  85. float Get_CPU_Temp()
  86. {
  87.     float temp;
  88.     char buf_cpu_temp_read[30];
  89.         int fd = open(TEMP_PATH, O_RDONLY);
  90.        
  91.     if (fd < 0)
  92.     {
  93.         printf("无法打开thermal_zone0/temp文件\n");
  94.         return 0;
  95.     }
  96.     if (read(fd,buf_cpu_temp_read,30) < 0)
  97.     {
  98.         printf("读取温度数据失败\n");
  99.         return 0;
  100.     }
  101.     return atoi(buf_cpu_temp_read)/1000.0;
  102. }
  103. void thread_resume()
  104. {
  105.         if (status == STOP)
  106.         {
  107.             pthread_mutex_lock(&mut);
  108.             status = RUN;
  109.             pthread_cond_signal(&cond);
  110.             printf("CPU温度检测线程恢复运行\n");
  111.             pthread_mutex_unlock(&mut);
  112.         }
  113.         else
  114.         {
  115.             printf("CPU温度检测线程一直在运行\n");
  116.         }
  117. }
  118. void thread_pause()
  119. {
  120.         if (status == RUN)
  121.         {
  122.                 pthread_mutex_lock(&mut);
  123.                 status = STOP;
  124.                 printf("CPU温度检测线程暂停(挂起)\n");
  125.                 pthread_mutex_unlock(&mut);
  126.         }
  127.         else
  128.         {
  129.                 printf("CPU温度检测线程一直在暂停\n");
  130.         }
  131. }
  132. char *buf_html;
  133. char a[90]={"HTTP/1.1 200 OK\nContent-Length:00075\nServer: Hatschi Server 1.0\nContent-Type: text/html\n\n"};
  134. int flag_get=0,flag_post=0,flag_keep_alive=0,flag_post_once=1,len_buf_html=0;
  135. int File_Read_Length(char* filename)
  136. {
  137.     FILE *f=fopen(filename,"rb");
  138.     if (!f)
  139.     {
  140.         printf("Can't open bin file!\n");
  141.         return 0;
  142.     }
  143.     fseek(f,0,SEEK_END);
  144.     int len = ftell(f);
  145.     fseek(f,0,SEEK_SET);
  146.     fclose(f);
  147.     return len;
  148. }
  149. void File_Read_All_Text(char* filename)
  150. {
  151.     FILE *f = fopen(filename,"r");
  152.     fseek(f,0,SEEK_END);
  153.     long len = ftell(f);
  154.     buf_html=(char*)malloc(len+1);
  155.     rewind(f);
  156.     fread(buf_html,sizeof(char),len,f);
  157.     buf_html[len] ='\n';
  158.     buf_html[len+1] ='\0';
  159. }
  160. void *Thread_Send(void *arg)
  161. {
  162.     int len,i;
  163.     float cpu_temp;
  164.     while(1)
  165.     {
  166.         if(flag_keep_alive&&flag_post_once)
  167.         {
  168.             flag_post_once=0;
  169.             if(flag_get)
  170.                 printf("收到客户端GET请求,服务器可进行一次POST操作\n");
  171.             else if(flag_post)
  172.                 printf("收到客户端POST回应,服务器可进行一次POST操作\n");
  173.             File_Read_All_Text("/home/proj/1.html");
  174.             len_buf_html=File_Read_Length("/home/proj/1.html");
  175.             printf("\n\nHTML文件长度:len_buf_html=%d\n\n",len_buf_html);
  176.             cpu_temp=Get_CPU_Temp();
  177.             printf("\n\nCPU温度:%f %.1f %.1f\n\n",cpu_temp,dht11_temp,dht11_humi);
  178.                         for(i=0;i<len_buf_html;i++)
  179.                                 if(buf_html[i]=='H'&&buf_html[i+1]=='U'&&buf_html[i+2]=='M'&&buf_html[i+3]=='1')
  180.                                         printf("\n\n----- i=%d -----\n\n",i);
  181.                        
  182.             buf_html[156]=(int)(cpu_temp)/10%10+'0';
  183.                         buf_html[157]=(int)(cpu_temp)%10+'0';
  184.             buf_html[159]=(int)(cpu_temp*10)%10+'0';
  185.             buf_html[180]=(int)(dht11_temp)/10%10+'0';
  186.             buf_html[181]=(int)(dht11_temp)%10+'0';
  187.             buf_html[183]=(int)(dht11_temp*10)%10+'0';
  188.             buf_html[204]=(int)(dht11_humi)/10%10+'0';
  189.             buf_html[205]=(int)(dht11_humi)%10+'0';
  190.             buf_html[207]=(int)(dht11_humi*10)%10+'0';
  191.                        
  192.             a[31]=len_buf_html/10000%10+'0';
  193.             a[32]=len_buf_html/1000%10+'0';
  194.             a[33]=len_buf_html/100%10+'0';
  195.             a[34]=len_buf_html/10%10+'0';
  196.             a[35]=len_buf_html%10+'0';
  197.             for(len=0;a[len]!='\0';len++)
  198.                 putchar(a[len]);
  199.             putchar('\n');
  200.             send(fd_socket_conn,a,len,0);
  201.             for(len=0;buf_html[len]!='\0';len++);
  202.             send(fd_socket_conn,buf_html,len,0);
  203.             close(fd_socket_conn);
  204.         }
  205.     }
  206. }
  207. int Char2Int(unsigned char s[])
  208. {
  209.     int result;
  210.     if('0'<=s[0]&&s[0]<='9'&&'0'<=s[1]&&s[1]<='9'&&'0'<=s[2]&&s[2]<='9'&&
  211.        '0'<=s[3]&&s[3]<='9'&&'0'<=s[4]&&s[4]<='9')
  212.         result=(s[0]-'0')*10000+(s[1]-'0')*1000+(s[2]-'0')*100+(s[3]-'0')*10+(s[4]-'0');
  213.     else if('0'<=s[0]&&s[0]<='9'&&'0'<=s[1]&&s[1]<='9'&&'0'<=s[2]&&s[2]<='9'&&
  214.             '0'<=s[3]&&s[3]<='9'&&s[4]=='\0')
  215.         result=(s[0]-'0')*1000+(s[1]-'0')*100+(s[2]-'0')*10+(s[3]-'0');
  216.     return result;
  217. }
  218. void LED_Control(int n)
  219. {
  220.     FILE *f=fopen("/sys/class/leds/status_usr0/brightness","w");
  221.     if (f==NULL)
  222.         printf("LED操作文件打开失败");
  223.     else
  224.         if(n==1)
  225.             fprintf(f,"%d",1);
  226.         else if(n==0)
  227.             fprintf(f,"%d",0);
  228.     fclose(f);
  229. }
  230. int main(int argc,char *argv[])
  231. {
  232.     int ret,locate=0;
  233.        
  234.         fd_dht11=open(DHT11_PATH,O_RDONLY);
  235.         pthread_create(&id2,NULL,Thread_CPU_Temp,NULL);
  236.        
  237.     socklen_t addrsize=sizeof(struct sockaddr);
  238.     struct sockaddr_in sockaddr_in_server,sockaddr_in_conn;
  239.     //初始化该结构体变��?
  240.     bzero(&sockaddr_in_server,sizeof(sockaddr_in_server));
  241.     sockaddr_in_server.sin_family=AF_INET;
  242.     sockaddr_in_server.sin_addr.s_addr=inet_addr(argv[1]);
  243.     sockaddr_in_server.sin_port=htons(Char2Int((unsigned char*)argv[2]));
  244.     fd_socket_server=socket(AF_INET,SOCK_STREAM,0);
  245.     if(fd_socket_server==-1)
  246.     {
  247.             printf("套接字创��?初始化失��?\n");
  248.             return -1;
  249.     }
  250.     ret=bind(fd_socket_server,(struct sockaddr *)&sockaddr_in_server,addrsize);
  251.     if(ret==-1)
  252.     {
  253.             printf("套接字绑定失��?\n");
  254.             return -1;
  255.     }
  256.     ret=listen(fd_socket_server,5);
  257.     if(ret==-1)
  258.     {
  259.             printf("服务器监听失��?\n");
  260.             return -1;
  261.     }
  262.     int i,j;
  263.     while(1)
  264.     {
  265.         fd_socket_conn=accept(fd_socket_server,(struct sockaddr *)&sockaddr_in_conn,&addrsize);
  266.         if(fd_socket_conn==-1)
  267.         {
  268.                 printf("服务器接听失��?\n");
  269.                 return -1;
  270.         }
  271.         else if(fd_socket_conn>=0)
  272.         {
  273.             printf("已有客户端成功连接服务器!\n");
  274.             ret=pthread_create(&id1,NULL,Thread_Send,NULL);
  275.             if(ret==0)
  276.                 printf("TCP发送阻塞线程创建成��?\n");
  277.         }
  278.         bzero(recvbuf,100);
  279.         recv(fd_socket_conn,recvbuf,1000,0);
  280.         printf("------\n%s\n------\n",recvbuf);
  281.         if(recvbuf[0]=='G'&&recvbuf[1]=='E'&&recvbuf[2]=='T')
  282.         {
  283.             printf("客户端浏览器发出GET请求\n");
  284.             flag_get=1;
  285.             flag_post=0;
  286.             flag_post_once=1;
  287.         }
  288.         if(recvbuf[0]=='P'&&recvbuf[1]=='O'&&recvbuf[2]=='S'&&recvbuf[3]=='T')
  289.         {
  290.             printf("客户端浏览器发出POST回应\n");
  291.             flag_get=0;
  292.             flag_post=1;
  293.             flag_post_once=1;
  294.         }
  295.         for(i=0;i<=1000;i++)
  296.         {
  297.             if(recvbuf[i]=='H'&&recvbuf[i+1]=='T'&&recvbuf[i+2]=='T'&&recvbuf[i+3]=='P'&&
  298.                recvbuf[i+4]=='/')
  299.             {
  300.                     printf("HTTP协议版本/类型��?");
  301.                     for(j=i;j<=i+7;j++)
  302.                         putchar(recvbuf[j]);
  303.                             putchar('\n');
  304.             }
  305.             if(recvbuf[i]=='H'&&recvbuf[i+1]=='o'&&recvbuf[i+2]=='s'&&recvbuf[i+3]=='t')
  306.             {
  307.                     printf("主机地址及端口号��?");
  308.                     for(j=i+6;j<=i+22;j++)
  309.                         putchar(recvbuf[j]);
  310.                             putchar('\n');
  311.             }
  312.             if(recvbuf[i]=='C'&&recvbuf[i+1]=='o'&&recvbuf[i+2]=='n'&&recvbuf[i+3]=='n'&&
  313.                recvbuf[i+4]=='e'&&recvbuf[i+5]=='c'&&recvbuf[i+6]=='t'&&recvbuf[i+7]=='i'&&
  314.                recvbuf[i+8]=='o'&&recvbuf[i+9]=='n')
  315.             {
  316.                     printf("连接方式��?");
  317.                     for(j=i+12;j<=i+21;j++)
  318.                         putchar(recvbuf[j]);
  319.                     putchar('\n');
  320.                     flag_keep_alive=1;
  321.             }
  322.             if(recvbuf[i]=='l'&&recvbuf[i+1]=='e'&&recvbuf[i+2]=='d'&&recvbuf[i+3]=='_'&&
  323.                recvbuf[i+4]=='s'&&recvbuf[i+5]=='w'&&recvbuf[i+6]=='i'&&recvbuf[i+7]=='t'&&
  324.                recvbuf[i+8]=='c'&&recvbuf[i+9]=='h'&&recvbuf[i+10]=='=')
  325.             {
  326.                 printf("检测到LED控制指令:\n");
  327.                 if(recvbuf[i+11]=='o'&&recvbuf[i+12]=='n')
  328.                 {
  329.                     printf("LED开\n");
  330.                     LED_Control(1);
  331.                 }
  332.                 else if(recvbuf[i+11]=='o'&&recvbuf[i+12]=='f'&&recvbuf[i+13]=='f')
  333.                 {
  334.                     printf("LED关\n");
  335.                     LED_Control(0);
  336.                 }
  337.             }
  338.         }
  339.     }
  340.         /*
  341.         while(1)
  342.         {
  343.             fd_socket=socket(AF_INET,SOCK_STREAM,0);
  344.             if(fd_socket==-1)
  345.             {
  346.                     printf("套接字创��?初始化失��?\n");
  347.                     return -1;
  348.             }
  349.             ret=connect(fd_socket,(struct sockaddr *)&sockaddr_in_settings,addrsize);
  350.             if(ret==0)
  351.             {
  352.                 printf("与服务器建立连接\n");
  353.                 ret=pthread_create(&id1,NULL,Thread_Send,NULL);
  354.                 if(ret==0)
  355.                     printf("TCP发送阻塞线程被创建!\n");
  356.                 break;
  357.             }
  358.         }
  359.         while(1)
  360.         {
  361.             bzero(recvbuf,100);
  362.             ret=recv(fd_socket,recvbuf,100,0);
  363.             if(ret==0)
  364.             {
  365.                 printf("与服务器失去连接\n");
  366.                 ret=pthread_cancel(id1);
  367.                 if(ret==0)
  368.                     printf("TCP发送阻塞线程被取消\n");
  369.                 break;
  370.             }
  371.             printf("服务器端发来信息��?s\n",recvbuf);
  372.         }
  373.         */
  374. }
不知道为啥使用source insight打开的话中文会乱码,不管了,编码选项只是小事,只是一些打印而已。



网页HTML源码也非常简单:
  1. <html>
  2. <head>
  3. <title>英蓓特MAAX IMX8网页实验</title>
  4. </head>
  5. <body>
  6. <p>MAAX IMX8网页服务器</p>
  7. <p>dontello1996</p>
  8. <p>方式:GET+POST</p>
  9. <p>CPU温度:  . ℃</p>
  10. <p>环境温度:  . ℃</p>
  11. <p>环境湿度:  . %</p>
  12. <p>LED灯控制实验</p>
  13. <form method="POST">
  14. <p><select name="led_switch">
  15.   <option value ="on">开</option>
  16.   <option value ="off">关</option>
  17. </select></p>
  18. <input type="submit" value="提交">
  19. </form>
  20. </body>
  21. </html>

设备树源码dts添加一个名为dht11的设备,重新编译设备树,并插入ko文件之后,会在/dev下生成dht11文件:
  1. /{
  2. dht11
  3. {
  4. compatible = "dht11";
  5. pinctrl-names = "default";
  6. };
22.jpg


编译完成后,使用
  1. ./main 192.168.1.4 6666
运行,指定服务器IP和端口,看看效果:
每刷新一次网页,就会读取一组新的CPU温度和温湿度数据:
21.jpg
IMG_20200823_191116.jpg


DHT11的驱动ko: DHT11.zip (39.58 KB, 下载次数: 0)
全部回复 0
暂无评论,快来抢沙发吧