驱动DHT11单总线温湿度传感器的方式与内核驱动GPIO读写的方式基本无差异,都是通过对/dev目录下的设备文件进行write/read操作,不同的是DHT11的读取需要不断切换GPIO输入输出状态并不断做轮询,其运行层面是驱动层,对于系统来说,驱动层代码的实时性要求和读写优先级都要高于应用层代码,即要将更多的CPU任务时间片资源放到驱动层代码中,也就只有这样,才能对DHT11这种延时响应时间要求是微秒级的单总线器件进行正常读写。废话不多说放上DHT11的驱动源码,这份代码参考了一位开发驱动的朋友@jackeyt,修改了一些小地方:
#include <linux/err.h>
  • #include <linux/gpio.h>
  • #include <linux/of_gpio.h>
  • #include <linux/gpio/consumer.h>
  • #include <linux/kernel.h>
  • #include <linux/module.h>
  • #include <linux/of.h>
  • #include <linux/platform_device.h>
  • #include <linux/property.h>
  • #include <linux/slab.h>
  • #include <linux/fs.h>
  • #include <linux/types.h>
  • #include <linux/delay.h>
  • #include <linux/device.h>
  • #include <asm/uaccess.h>
  • static int dht11_major = 0;
  • static int dht11_gpio=80;
  • static struct class *dht11_class;//类
  • static struct device *dht11_dev;//设备
  • static const char* dht11_name = "dht11";
  • typedef struct        DHT11_SENSOR_DATA
  • {
  •         u16 temp;//温度
  •         u16 hum;//湿度
  • }dht11_data;
  • #define DHT11_DQ_High    gpio_direction_output(dht11_gpio, 1)
  • #define DHT11_DQ_Low     gpio_direction_output(dht11_gpio, 0)
  • #define DHT11_IO_IN                 gpio_direction_input(dht11_gpio)
  • #define delay_us(x)                udelay(x)
  • #define delay_ms(x)                msleep(x)
  • static u8 DHT11_Read_DQ(void)   
  • {
  •         DHT11_IO_IN;
  •         return gpio_get_value(dht11_gpio);
  • }
  • //复位DHT11
  • static void DHT11_Rst(void)   
  • {                 
  •         DHT11_DQ_Low;
  •         msleep (20);  //拉低至少18ms
  •         DHT11_DQ_High; //DQ=1
  •         delay_us (30);  //主机拉高20~40us
  • }
  • //等待DHT11的回应
  • //返回1:未检测到DHT11的存在
  • //返回0:存在
  • static u8 DHT11_Check(void)   
  • {   
  •         u8 retry=0;//定义临时变量
  •         DHT11_IO_IN;//SET INPUT
  •         while ((DHT11_Read_DQ()==1)&&retry<100)//DHT11会拉低40~80us
  •         {
  •                 retry++;
  •                 delay_us(1);
  •         };
  •         if(retry>=100)return 1;
  •         else retry=0;
  •         while ((DHT11_Read_DQ()==0)&&retry<100)//DHT11拉低后会再次拉高40~80us
  •         {
  •                 retry++;
  •                 delay_us(1);
  •         };
  •         if(retry>=100)return 1;   
  •         return 0;
  • }
  • //从DHT11读取一个位
  • //返回值:1/0
  • static u8 DHT11_Read_Bit(void)  
  • {
  •         u8 retry=0;
  •         while((DHT11_Read_DQ()==1)&&retry<100)//等待变为低电平
  •         {
  •                 retry++;
  •                 delay_us(1);
  •         }
  •         retry=0;
  •         while((DHT11_Read_DQ()==0)&&retry<100)//等待变高电平
  •         {
  •                 retry++;
  •                 delay_us(1);
  •         }
  •         delay_us(40);//等待40us
  •         if(DHT11_Read_DQ()==1)
  •         return 1;
  •         else
  •         return 0;   
  • }
  • //从DHT11读取一个字节
  • //返回值:读到的数据
  • static u8 DHT11_Read_Byte(void)   
  • {        
  •     u8 i,dat;
  •     dat=0;
  •         for (i=0;i<8;i++)
  •         {
  •                 dat<<=1;
  •                 dat|=DHT11_Read_Bit();
  •         }   
  •         return dat;
  • }
  • //从DHT11读取一次数据
  • //temp:温度值(范围:0~50°)
  • //humi:湿度值(范围:20%~90%)
  • //返回值:0,正常;1,读取失败
  • static u8 DHT11_Read_Data(u16 *temp,u16 *humi)   
  • {        
  •         u8 buf[5];
  •         u8 i;
  •         DHT11_Rst();
  •         if(DHT11_Check()==0)
  •         {
  •                 for(i=0;i<5;i++)//读取40位数据
  •                 {
  •                         buf[i]=DHT11_Read_Byte();
  •                 }
  •                 if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
  •                 {
  •                         *humi=buf[0]<<8|buf[1];
  •                         *temp=buf[2]<<8|buf[3];
  •                         printk("buf=%d,%d,%d,%d,%d\n",buf[0],buf[1],buf[2],buf[3],buf[4]);
  •                 }
  •         }else return 1;
  •         return 0;   
  • }
  • //初始化DHT11的IO口 DQ 同时检测DHT11的存在
  • //返回1:不存在
  • //返回0:存在     
  • static void DHT11_Init(void)
  • {     
  •         DHT11_Rst();  //复位DHT11
  •         DHT11_Check();//等待DHT11的回应
  • }
  • int DHT11_open(struct inode *inode, struct file *flips)
  • {
  •         printk("--------------%s--------------\n",__FUNCTION__);
  •         return 0;
  • }
  • static ssize_t DHT11_read(struct file *file, char __user *buf,
  •                     size_t nbytes, loff_t *ppos)
  • {       
  •         printk("--------------%s--------------\n",__FUNCTION__);
  •        
  •         dht11_data Last_dht11_data;
  •         if(DHT11_Read_Data(&Last_dht11_data.temp,&Last_dht11_data.hum) == 0)//读取温湿度值
  •         {
  •                 if (raw_copy_to_user(buf,&Last_dht11_data,sizeof(Last_dht11_data)) )
  •                 {
  •                         return EFAULT ;
  •                 }
  •         }
  • }
  • static int DHT11_close(struct inode *inode, struct file *flip)
  • {
  •         printk("--------------%s--------------\n",__FUNCTION__);
  •         return 0;
  • }
  • static struct file_operations dht11_fops = {
  •         .owner = THIS_MODULE,
  •         .read = DHT11_read,
  •         .open = DHT11_open,
  •         .release = DHT11_close,
  • };
  • static const struct of_device_id of_dht11_match[] = {
  •         { .compatible = "dht11", },
  •         {},
  • };
  • MODULE_DEVICE_TABLE(of, of_dht11_match);
  • static int dht11_probe(struct platform_device *pdev)
  • {
  •         int ret;  
  •         enum of_gpio_flags flag;//(flag == OF_GPIO_ACTIVE_LOW) ?
  •         printk("-------%s-------------\n", __FUNCTION__);
  •        
  •     struct device_node *dht11_gpio_node = pdev->dev.of_node;
  •        
  •         //dht11_gpio = of_get_named_gpio_flags(dht11_gpio_node->child, "gpios", 0, &flag);
  •         if (!gpio_is_valid(dht11_gpio))
  •         {
  •             printk("dht11-gpio: %d is invalid\n", dht11_gpio);
  •                 return -ENODEV;
  •     }
  •         else
  •                 printk("dht11-gpio: %d is valid!\n", dht11_gpio);
  •         if (gpio_request(dht11_gpio, "dht11-gpio"))
  •         {
  •         printk("gpio %d request failed!\n", dht11_gpio);
  •         gpio_free(dht11_gpio);
  •         return -ENODEV;
  •     }
  •         else
  •                 printk("gpio %d request success!\n", dht11_gpio);
  •         //能够读到配置信息之后就可以开始创建设备节点
  •         dht11_major = register_chrdev(0, "dht11",&dht11_fops);
  •         if(dht11_major <0)
  •         {
  •                 printk(KERN_ERR "reg error!\n");
  •                 goto err_0;               
  •         }
  •         else
  •                 printk("dht11_major =%d\n",dht11_major);
  •        
  •         dht11_class = class_create(THIS_MODULE,"dht11_class");//creat class
  •         if( IS_ERR(dht11_class))
  •         {
  •                 printk(KERN_ERR "fail create class\n");
  •                 ret = PTR_ERR(dht11_class);
  •                 goto err_1;
  •         }
  •        
  •         //creat dht11_dev--->>/dev/dht11_dev
  •         dht11_dev = device_create(dht11_class, NULL,MKDEV(dht11_major,0), NULL, dht11_name);
  •         if(IS_ERR(dht11_dev))
  •         {
  •                 printk(KERN_ERR "fail create device!\n");
  •                 ret = PTR_ERR(dht11_dev);
  •                 goto err_2;               
  •         }
  •        
  •         //init dht11
  •         DHT11_Init();
  •         printk("dht11 Initing...\n");
  •         return 0;
  •        
  • err_2:
  •                 device_destroy(dht11_class,MKDEV(dht11_major,0));
  • err_1:
  •                 class_destroy(dht11_class);
  • err_0:
  •                 unregister_chrdev(dht11_major,dht11_name);       
  •                 return -1;
  • }
  • static int dht11_remove(struct platform_device *pdev)
  • {
  •         printk("-------%s-------------\n", __FUNCTION__);
  •         device_destroy(dht11_class,MKDEV(dht11_major,0));
  •         class_destroy(dht11_class);
  •         unregister_chrdev(dht11_major,dht11_name);
  •         return 0;
  • }
  • static void dht11_shutdown(struct platform_device *pdev)
  • {
  •         printk("-------%s-------------\n", __FUNCTION__);
  • }
  • static struct platform_driver dht11_driver = {
  •         .probe                = dht11_probe,
  •         .remove                = dht11_remove,
  •         .shutdown        = dht11_shutdown,
  •         .driver                = {
  •                 .name        = "dht11_driver",
  •                 .of_match_table = of_dht11_match,
  •         },
  • };
  • module_platform_driver(dht11_driver);
  • 复制代码


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

    可以看到,DHT11驱动源码中的dht11_probe函数加入的printk打印在插入的时候就已经生效了。
    然后是单独对DHT11器件进行简单读写的main函数:
    这里我注意到一点,对于/dev/dht11设备,读取间隔是1秒1次,不管是在主线程(main())中还是在新开辟的线程中,都必须要有这个间隔,不然读取会失败,一般对于DHT11这种轮询器件而言,都是有必要开启一个单独线程进行读取的,比较Linux中线程资源非常充足,而DHT11对于实时性要求又比较高。
    然后我这边套用一套以前自己写的HTTP网页服务器代码,非常简单,是通过TCP方式进行GET/POST操作,简单得不能再简单那种:
    #include <stdio.h>
  • #include <stdlib.h>
  • #include <stdbool.h>
  • #include <stdint.h>
  • #include <string.h>
  • #include <errno.h>
  • #include <fcntl.h>
  • #include <time.h>
  • #include <unistd.h>
  • #include <string.h>
  • #include <fcntl.h>
  • #include <unistd.h>
  • #include <pthread.h>
  • #include <linux/input.h>
  • #include <sys/mman.h>
  • #include <sys/socket.h>
  • #include <sys/types.h>
  • #include <sys/stat.h>
  • #include <arpa/inet.h>
  • #include <netinet/in.h>
  • #define RUN  1
  • #define STOP 0
  • pthread_t id1,id2;
  • int fd_socket_server,fd_socket_conn;
  • pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
  • pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  • char sendbuf[420],recvbuf[1000];
  • int thread_flag=0,status=STOP;
  • #define TEMP_PATH "/sys/class/thermal/thermal_zone0/temp"
  • #define DHT11_PATH "/dev/dht11"
  • typedef struct
  • {
  •         short temp;
  •         short humi;
  • }dht11_data;
  • dht11_data dht11_data1;
  • int fd_dht11;
  • float dht11_temp,dht11_humi;
  • void *Thread_CPU_Temp(void *arg)
  • {
  •     void *ret;
  •     int fd,retval;
  •     float temp=0;
  •     char buf[30];
  •         while(1)
  •         {
  •                 read( fd_dht11 , &dht11_data1 , sizeof(dht11_data1));
  •                 if(dht11_data1.temp != 0xffff)
  •                 {
  •                         dht11_temp = (dht11_data1.temp>>8)*1.0 + (dht11_data1.temp&0xff)*0.1;
  •                         dht11_humi = (dht11_data1.humi>>8)*1.0 + (dht11_data1.humi&0xff)*0.1;
  •                 }
  •                 sleep(1);
  •         }
  •     while(1)
  •     {
  •                 //                pthread_mutex_lock(&mut);
  •                 //                  while(!status)
  •                 //                  {
  •                 //                          pthread_cond_wait(&cond, &mut);
  •                 //                  }
  •                 //                  pthread_mutex_unlock(&mut);
  •         fd = open(TEMP_PATH, O_RDONLY);
  •         if (fd<0)
  •         {
  •             fprintf(stderr,"无法打开thermal_zone0/temp文件\n");
  •             return ret;
  •         }
  •         if (read(fd,buf,30)<0)
  •         {
  •             fprintf(stderr,"读取温度数据失败\n");
  •             return ret;
  •         }
  •         temp = atoi(buf)/1000.0;
  •         printf("CPU温度��?.1f\n",temp);
  •         buf[0]=(int)temp/10%10+'0';
  •         buf[1]=(int)temp%10+'0';
  •         buf[2]='.';
  •         buf[3]=(int)(temp*10)%10+'0';
  •         buf[4]=0;
  •         send(fd_socket_conn,buf,5,0);
  •         sleep(1);
  •     }
  • }
  • float Get_CPU_Temp()
  • {
  •     float temp;
  •     char buf_cpu_temp_read[30];
  •         int fd = open(TEMP_PATH, O_RDONLY);
  •        
  •     if (fd < 0)
  •     {
  •         printf("无法打开thermal_zone0/temp文件\n");
  •         return 0;
  •     }
  •     if (read(fd,buf_cpu_temp_read,30) < 0)
  •     {
  •         printf("读取温度数据失败\n");
  •         return 0;
  •     }
  •     return atoi(buf_cpu_temp_read)/1000.0;
  • }
  • void thread_resume()
  • {
  •         if (status == STOP)
  •         {
  •             pthread_mutex_lock(&mut);
  •             status = RUN;
  •             pthread_cond_signal(&cond);
  •             printf("CPU温度检测线程恢复运行\n");
  •             pthread_mutex_unlock(&mut);
  •         }
  •         else
  •         {
  •             printf("CPU温度检测线程一直在运行\n");
  •         }
  • }
  • void thread_pause()
  • {
  •         if (status == RUN)
  •         {
  •                 pthread_mutex_lock(&mut);
  •                 status = STOP;
  •                 printf("CPU温度检测线程暂停(挂起)\n");
  •                 pthread_mutex_unlock(&mut);
  •         }
  •         else
  •         {
  •                 printf("CPU温度检测线程一直在暂停\n");
  •         }
  • }
  • char *buf_html;
  • char a[90]={"HTTP/1.1 200 OK\nContent-Length:00075\nServer: Hatschi Server 1.0\nContent-Type: text/html\n\n"};
  • int flag_get=0,flag_post=0,flag_keep_alive=0,flag_post_once=1,len_buf_html=0;
  • int File_Read_Length(char* filename)
  • {
  •     FILE *f=fopen(filename,"rb");
  •     if (!f)
  •     {
  •         printf("Can't open bin file!\n");
  •         return 0;
  •     }
  •     fseek(f,0,SEEK_END);
  •     int len = ftell(f);
  •     fseek(f,0,SEEK_SET);
  •     fclose(f);
  •     return len;
  • }
  • void File_Read_All_Text(char* filename)
  • {
  •     FILE *f = fopen(filename,"r");
  •     fseek(f,0,SEEK_END);
  •     long len = ftell(f);
  •     buf_html=(char*)malloc(len+1);
  •     rewind(f);
  •     fread(buf_html,sizeof(char),len,f);
  •     buf_html[len] ='\n';
  •     buf_html[len+1] ='\0';
  • }
  • void *Thread_Send(void *arg)
  • {
  •     int len,i;
  •     float cpu_temp;
  •     while(1)
  •     {
  •         if(flag_keep_alive&&flag_post_once)
  •         {
  •             flag_post_once=0;
  •             if(flag_get)
  •                 printf("收到客户端GET请求,服务器可进行一次POST操作\n");
  •             else if(flag_post)
  •                 printf("收到客户端POST回应,服务器可进行一次POST操作\n");
  •             File_Read_All_Text("/home/proj/1.html");
  •             len_buf_html=File_Read_Length("/home/proj/1.html");
  •             printf("\n\nHTML文件长度:len_buf_html=%d\n\n",len_buf_html);
  •             cpu_temp=Get_CPU_Temp();
  •             printf("\n\nCPU温度:%f %.1f %.1f\n\n",cpu_temp,dht11_temp,dht11_humi);
  •                         for(i=0;i<len_buf_html;i++)
  •                                 if(buf_html[i]=='H'&&buf_html[i+1]=='U'&&buf_html[i+2]=='M'&&buf_html[i+3]=='1')
  •                                         printf("\n\n----- i=%d -----\n\n",i);
  •                        
  •             buf_html[156]=(int)(cpu_temp)/10%10+'0';
  •                         buf_html[157]=(int)(cpu_temp)%10+'0';
  •             buf_html[159]=(int)(cpu_temp*10)%10+'0';
  •             buf_html[180]=(int)(dht11_temp)/10%10+'0';
  •             buf_html[181]=(int)(dht11_temp)%10+'0';
  •             buf_html[183]=(int)(dht11_temp*10)%10+'0';
  •             buf_html[204]=(int)(dht11_humi)/10%10+'0';
  •             buf_html[205]=(int)(dht11_humi)%10+'0';
  •             buf_html[207]=(int)(dht11_humi*10)%10+'0';
  •                        
  •             a[31]=len_buf_html/10000%10+'0';
  •             a[32]=len_buf_html/1000%10+'0';
  •             a[33]=len_buf_html/100%10+'0';
  •             a[34]=len_buf_html/10%10+'0';
  •             a[35]=len_buf_html%10+'0';
  •             for(len=0;a[len]!='\0';len++)
  •                 putchar(a[len]);
  •             putchar('\n');
  •             send(fd_socket_conn,a,len,0);
  •             for(len=0;buf_html[len]!='\0';len++);
  •             send(fd_socket_conn,buf_html,len,0);
  •             close(fd_socket_conn);
  •         }
  •     }
  • }
  • int Char2Int(unsigned char s[])
  • {
  •     int result;
  •     if('0'<=s[0]&&s[0]<='9'&&'0'<=s[1]&&s[1]<='9'&&'0'<=s[2]&&s[2]<='9'&&
  •        '0'<=s[3]&&s[3]<='9'&&'0'<=s[4]&&s[4]<='9')
  •         result=(s[0]-'0')*10000+(s[1]-'0')*1000+(s[2]-'0')*100+(s[3]-'0')*10+(s[4]-'0');
  •     else if('0'<=s[0]&&s[0]<='9'&&'0'<=s[1]&&s[1]<='9'&&'0'<=s[2]&&s[2]<='9'&&
  •             '0'<=s[3]&&s[3]<='9'&&s[4]=='\0')
  •         result=(s[0]-'0')*1000+(s[1]-'0')*100+(s[2]-'0')*10+(s[3]-'0');
  •     return result;
  • }
  • void LED_Control(int n)
  • {
  •     FILE *f=fopen("/sys/class/leds/status_usr0/brightness","w");
  •     if (f==NULL)
  •         printf("LED操作文件打开失败");
  •     else
  •         if(n==1)
  •             fprintf(f,"%d",1);
  •         else if(n==0)
  •             fprintf(f,"%d",0);
  •     fclose(f);
  • }
  • int main(int argc,char *argv[])
  • {
  •     int ret,locate=0;
  •        
  •         fd_dht11=open(DHT11_PATH,O_RDONLY);
  •         pthread_create(&id2,NULL,Thread_CPU_Temp,NULL);
  •        
  •     socklen_t addrsize=sizeof(struct sockaddr);
  •     struct sockaddr_in sockaddr_in_server,sockaddr_in_conn;
  •     //初始化该结构体变��?
  •     bzero(&sockaddr_in_server,sizeof(sockaddr_in_server));
  •     sockaddr_in_server.sin_family=AF_INET;
  •     sockaddr_in_server.sin_addr.s_addr=inet_addr(argv[1]);
  •     sockaddr_in_server.sin_port=htons(Char2Int((unsigned char*)argv[2]));
  •     fd_socket_server=socket(AF_INET,SOCK_STREAM,0);
  •     if(fd_socket_server==-1)
  •     {
  •             printf("套接字创��?初始化失��?\n");
  •             return -1;
  •     }
  •     ret=bind(fd_socket_server,(struct sockaddr *)&sockaddr_in_server,addrsize);
  •     if(ret==-1)
  •     {
  •             printf("套接字绑定失��?\n");
  •             return -1;
  •     }
  •     ret=listen(fd_socket_server,5);
  •     if(ret==-1)
  •     {
  •             printf("服务器监听失��?\n");
  •             return -1;
  •     }
  •     int i,j;
  •     while(1)
  •     {
  •         fd_socket_conn=accept(fd_socket_server,(struct sockaddr *)&sockaddr_in_conn,&addrsize);
  •         if(fd_socket_conn==-1)
  •         {
  •                 printf("服务器接听失��?\n");
  •                 return -1;
  •         }
  •         else if(fd_socket_conn>=0)
  •         {
  •             printf("已有客户端成功连接服务器!\n");
  •             ret=pthread_create(&id1,NULL,Thread_Send,NULL);
  •             if(ret==0)
  •                 printf("TCP发送阻塞线程创建成��?\n");
  •         }
  •         bzero(recvbuf,100);
  •         recv(fd_socket_conn,recvbuf,1000,0);
  •         printf("------\n%s\n------\n",recvbuf);
  •         if(recvbuf[0]=='G'&&recvbuf[1]=='E'&&recvbuf[2]=='T')
  •         {
  •             printf("客户端浏览器发出GET请求\n");
  •             flag_get=1;
  •             flag_post=0;
  •             flag_post_once=1;
  •         }
  •         if(recvbuf[0]=='P'&&recvbuf[1]=='O'&&recvbuf[2]=='S'&&recvbuf[3]=='T')
  •         {
  •             printf("客户端浏览器发出POST回应\n");
  •             flag_get=0;
  •             flag_post=1;
  •             flag_post_once=1;
  •         }
  •         for(i=0;i<=1000;i++)
  •         {
  •             if(recvbuf[i]=='H'&&recvbuf[i+1]=='T'&&recvbuf[i+2]=='T'&&recvbuf[i+3]=='P'&&
  •                recvbuf[i+4]=='/')
  •             {
  •                     printf("HTTP协议版本/类型��?");
  •                     for(j=i;j<=i+7;j++)
  •                         putchar(recvbuf[j]);
  •                             putchar('\n');
  •             }
  •             if(recvbuf[i]=='H'&&recvbuf[i+1]=='o'&&recvbuf[i+2]=='s'&&recvbuf[i+3]=='t')
  •             {
  •                     printf("主机地址及端口号��?");
  •                     for(j=i+6;j<=i+22;j++)
  •                         putchar(recvbuf[j]);
  •                             putchar('\n');
  •             }
  •             if(recvbuf[i]=='C'&&recvbuf[i+1]=='o'&&recvbuf[i+2]=='n'&&recvbuf[i+3]=='n'&&
  •                recvbuf[i+4]=='e'&&recvbuf[i+5]=='c'&&recvbuf[i+6]=='t'&&recvbuf[i+7]=='i'&&
  •                recvbuf[i+8]=='o'&&recvbuf[i+9]=='n')
  •             {
  •                     printf("连接方式��?");
  •                     for(j=i+12;j<=i+21;j++)
  •                         putchar(recvbuf[j]);
  •                     putchar('\n');
  •                     flag_keep_alive=1;
  •             }
  •             if(recvbuf[i]=='l'&&recvbuf[i+1]=='e'&&recvbuf[i+2]=='d'&&recvbuf[i+3]=='_'&&
  •                recvbuf[i+4]=='s'&&recvbuf[i+5]=='w'&&recvbuf[i+6]=='i'&&recvbuf[i+7]=='t'&&
  •                recvbuf[i+8]=='c'&&recvbuf[i+9]=='h'&&recvbuf[i+10]=='=')
  •             {
  •                 printf("检测到LED控制指令:\n");
  •                 if(recvbuf[i+11]=='o'&&recvbuf[i+12]=='n')
  •                 {
  •                     printf("LED开\n");
  •                     LED_Control(1);
  •                 }
  •                 else if(recvbuf[i+11]=='o'&&recvbuf[i+12]=='f'&&recvbuf[i+13]=='f')
  •                 {
  •                     printf("LED关\n");
  •                     LED_Control(0);
  •                 }
  •             }
  •         }
  •     }
  •         /*
  •         while(1)
  •         {
  •             fd_socket=socket(AF_INET,SOCK_STREAM,0);
  •             if(fd_socket==-1)
  •             {
  •                     printf("套接字创��?初始化失��?\n");
  •                     return -1;
  •             }
  •             ret=connect(fd_socket,(struct sockaddr *)&sockaddr_in_settings,addrsize);
  •             if(ret==0)
  •             {
  •                 printf("与服务器建立连接\n");
  •                 ret=pthread_create(&id1,NULL,Thread_Send,NULL);
  •                 if(ret==0)
  •                     printf("TCP发送阻塞线程被创建!\n");
  •                 break;
  •             }
  •         }
  •         while(1)
  •         {
  •             bzero(recvbuf,100);
  •             ret=recv(fd_socket,recvbuf,100,0);
  •             if(ret==0)
  •             {
  •                 printf("与服务器失去连接\n");
  •                 ret=pthread_cancel(id1);
  •                 if(ret==0)
  •                     printf("TCP发送阻塞线程被取消\n");
  •                 break;
  •             }
  •             printf("服务器端发来信息��?s\n",recvbuf);
  •         }
  •         */
  • }
  • 复制代码
    不知道为啥使用source insight打开的话中文会乱码,不管了,编码选项只是小事,只是一些打印而已。



    网页HTML源码也非常简单:
    <html>
  • <head>
  • <title>英蓓特MAAX IMX8网页实验</title>
  • </head>
  • <body>
  • <p>MAAX IMX8网页服务器</p>
  • <p>dontello1996</p>
  • <p>方式:GET+POST</p>
  • <p>CPU温度:  . ℃</p>
  • <p>环境温度:  . ℃</p>
  • <p>环境湿度:  . %</p>
  • <p>LED灯控制实验</p>
  • <form method="POST">
  • <p><select name="led_switch">
  •   <option value ="on">开</option>
  •   <option value ="off">关</option>
  • </select></p>
  • <input type="submit" value="提交">
  • </form>
  • </body>
  • </html>
  • 复制代码

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


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


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