青浦网站开发,拍卖网站建设方案,素材网站推广方案,免费观看电影电视剧的软件目录
0、设置ip
1、修改显示界面
2、 修改客户端
3、 修改服务器程序通信部分
4、 修改驱动处理程序
5、 重写驱动程序
6、 展示 0、设置ip
因为ifconfig命令要被淘汰了#xff0c;所以我们改成使用ip命令设置ubuntu的ip
ip addr add 192.168.5.10/24 dev ens36
ip …目录
0、设置ip
1、修改显示界面
2、 修改客户端
3、 修改服务器程序通信部分
4、 修改驱动处理程序
5、 重写驱动程序
6、 展示 0、设置ip
因为ifconfig命令要被淘汰了所以我们改成使用ip命令设置ubuntu的ip
ip addr add 192.168.5.10/24 dev ens36
ip addr show 1、修改显示界面 之前共用一个get value现在给每个人一个单独的显示框 2、 修改客户端 #dht11elif cmd[2] 0 and cmd[3] 5:if cmd[4] g:global_var.TEMcmd[4]cmd[5]global_var.HUMcmd[6]cmd[7]message f{global_var.TEM}°C {global_var.HUM}%window[DHT11_O].update(message)else:print(DHT11: message ERROR) elif event dht11:set_tx_buf(dht11, g)send_cmd(client_socket) DHT11 测量温度的精度为± 2℃检测范围为-20℃ -60℃。湿度的精度为± 5%RH检测范围为 5%RH-95%RH常用于对精度和实时性要求不高的温湿度测量场合。
所以温度要用三位数表示把低温也加上湿度的话两位就够了 #dht11elif cmd[2] 0 and cmd[3] 5:if cmd[4] g:global_var.TEMcmd[5]cmd[6]cmd[7]global_var.HUMcmd[8]cmd[9]message f{global_var.TEM}°C {global_var.HUM}%window[DHT11_O].update(message)else:print(DHT11: message ERROR)
3、 修改服务器程序通信部分 printf(dht11!!!\n);if (g cmd[4]){opt dht11_handle(buf);tx_buffer buf;}printf(%s\n,tx_buffer); if (send(acceptfd, tx_buffer, strlen(tx_buffer), 0) 0){perror(send failed); }break;
局部变量太多了东西展示都给driver_handele做
4、 修改驱动处理程序
/*
*author : xintianyu
*function : Handle dht11 Settings
*date : 2024-4-20
-----------------------
author date modify*/
int dht11_handle(char *data)
{/*传入参数后面要做通用处理使用空指针*/char *device /dev/cebss_dht11;unsigned char buf[2];int ret NOERROR;static int fd;/* 打开文件 */fd open(device, O_RDWR);if (fd -1){printf(can not open file %s\n, device);return ERROR;}
read:if (read(fd, buf, 2) 2){printf(get Humidity: %d, Temperature : %d\n, buf[0], buf[1]);sprintf(data,005g%d%d, buf[0], buf[1]);}else{sleep(5);printf(get dht11: -1\n);goto read;}close(fd);return ret;
} 5、 重写驱动程序
#include asm-generic/errno-base.h
#include asm-generic/gpio.h
#include linux/jiffies.h
#include linux/module.h
#include linux/poll.h
#include linux/delay.h
#include linux/fs.h
#include linux/errno.h
#include linux/miscdevice.h
#include linux/kernel.h
#include linux/major.h
#include linux/mutex.h
#include linux/proc_fs.h
#include linux/seq_file.h
#include linux/stat.h
#include linux/init.h
#include linux/device.h
#include linux/tty.h
#include linux/kmod.h
#include linux/gfp.h
#include linux/gpio/consumer.h
#include linux/platform_device.h
#include linux/of_gpio.h
#include linux/of_irq.h
#include linux/interrupt.h
#include linux/irq.h
#include linux/slab.h
#include linux/fcntl.h
#include linux/timer.hstruct gpio_desc{int gpio;int irq;char *name;int key;struct timer_list key_timer;
} ;static struct gpio_desc gpios[] {{115, 0, dht11, },
};/* 主设备号 */
static int major 0;
static struct class *gpio_class;static u64 g_dht11_irq_time[84];
static int g_dht11_irq_cnt 0;/* 环形缓冲区 */
#define BUF_LEN 128
static char g_keys[BUF_LEN];
static int r, w;struct fasync_struct *button_fasync;static irqreturn_t dht11_isr(int irq, void *dev_id);
static void parse_dht11_datas(void);#define NEXT_POS(x) ((x1) % BUF_LEN)static int is_key_buf_empty(void)
{return (r w);
}static int is_key_buf_full(void)
{return (r NEXT_POS(w));
}static void put_key(char key)
{if (!is_key_buf_full()){g_keys[w] key;w NEXT_POS(w);}
}static char get_key(void)
{char key 0;if (!is_key_buf_empty()){key g_keys[r];r NEXT_POS(r);}return key;
}static DECLARE_WAIT_QUEUE_HEAD(gpio_wait);// static void key_timer_expire(struct timer_list *t)
static void key_timer_expire(unsigned long data)
{// 解析数据, 放入环形buffer, 唤醒APPparse_dht11_datas();
}/* 实现对应的open/read/write等函数填入file_operations结构体 */
static ssize_t dht11_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{int err;char kern_buf[2];if (size ! 2)return -EINVAL;g_dht11_irq_cnt 0;/* 1. 发送18ms的低脉冲 */err gpio_request(gpios[0].gpio, gpios[0].name);gpio_direction_output(gpios[0].gpio, 0);gpio_free(gpios[0].gpio);mdelay(18);gpio_direction_input(gpios[0].gpio); /* 引脚变为输入方向, 由上拉电阻拉为1 *//* 2. 注册中断 */err request_irq(gpios[0].irq, dht11_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, gpios[0].name, gpios[0]);mod_timer(gpios[0].key_timer, jiffies 10); /* 3. 休眠等待数据 */wait_event_interruptible(gpio_wait, !is_key_buf_empty());free_irq(gpios[0].irq, gpios[0]);//printk(%s %s %d\n, __FILE__, __FUNCTION__, __LINE__);/* 设置DHT11 GPIO引脚的初始状态: output 1 */err gpio_request(gpios[0].gpio, gpios[0].name);if (err){printk(%s %s %d, gpio_request err\n, __FILE__, __FUNCTION__, __LINE__);}gpio_direction_output(gpios[0].gpio, 1);gpio_free(gpios[0].gpio);/* 4. copy_to_user */kern_buf[0] get_key();kern_buf[1] get_key();printk(get val : 0x%x, 0x%x\n, kern_buf[0], kern_buf[1]);if ((kern_buf[0] (char)-1) (kern_buf[1] (char)-1)){printk(get err val\n);return -EIO;}err copy_to_user(buf, kern_buf, 2);return 2;
}static int dht11_release (struct inode *inode, struct file *filp)
{return 0;
}/* 定义自己的file_operations结构体 */
static struct file_operations dht11_drv {.owner THIS_MODULE,.read dht11_read,.release dht11_release,
};static void parse_dht11_datas(void)
{int i;u64 high_time;unsigned char data 0;int bits 0;unsigned char datas[5];int byte 0;unsigned char crc;/* 数据个数: 可能是81、82、83、84 */if (g_dht11_irq_cnt 81){/* 出错 */put_key(-1);put_key(-1);// 唤醒APPwake_up_interruptible(gpio_wait);g_dht11_irq_cnt 0;return;}// 解析数据for (i g_dht11_irq_cnt - 80; i g_dht11_irq_cnt; i2){high_time g_dht11_irq_time[i] - g_dht11_irq_time[i-1];data 1;if (high_time 50000) /* data 1 */{data | 1;}bits;if (bits 8){datas[byte] data;data 0;bits 0;byte;}}// 放入环形buffercrc datas[0] datas[1] datas[2] datas[3];if (crc datas[4]){put_key(datas[0]);put_key(datas[2]);}else{put_key(-1);put_key(-1);}g_dht11_irq_cnt 0;// 唤醒APPwake_up_interruptible(gpio_wait);
}static irqreturn_t dht11_isr(int irq, void *dev_id)
{struct gpio_desc *gpio_desc dev_id;u64 time;/* 1. 记录中断发生的时间 */time ktime_get_ns();g_dht11_irq_time[g_dht11_irq_cnt] time;/* 2. 累计次数 */g_dht11_irq_cnt;/* 3. 次数足够: 解析数据, 放入环形buffer, 唤醒APP */if (g_dht11_irq_cnt 84){del_timer(gpio_desc-key_timer);parse_dht11_datas();}return IRQ_HANDLED;
}/* 在入口函数 */
static int __init dht11_init(void)
{int err;int i;int count sizeof(gpios)/sizeof(gpios[0]);printk(%s %s line %d\n, __FILE__, __FUNCTION__, __LINE__);for (i 0; i count; i){ gpios[i].irq gpio_to_irq(gpios[i].gpio);/* 设置DHT11 GPIO引脚的初始状态: output 1 */err gpio_request(gpios[i].gpio, gpios[i].name);gpio_direction_output(gpios[i].gpio, 1);gpio_free(gpios[i].gpio);setup_timer(gpios[i].key_timer, key_timer_expire, (unsigned long)gpios[i]);//timer_setup(gpios[i].key_timer, key_timer_expire, 0);//gpios[i].key_timer.expires ~0;//add_timer(gpios[i].key_timer);//err request_irq(gpios[i].irq, dht11_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 100ask_gpio_key, gpios[i]);}/* 注册file_operations */major register_chrdev(0, 100ask_dht11, dht11_drv); /* /dev/gpio_desc */gpio_class class_create(THIS_MODULE, 100ask_dht11_class);if (IS_ERR(gpio_class)) {printk(%s %s line %d\n, __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, 100ask_dht11);return PTR_ERR(gpio_class);}device_create(gpio_class, NULL, MKDEV(major, 0), NULL, mydht11); /* /dev/mydht11 */return err;
}/* 有入口函数就应该有出口函数卸载驱动程序时就会去调用这个出口函数*/
static void __exit dht11_exit(void)
{int i;int count sizeof(gpios)/sizeof(gpios[0]);printk(%s %s line %d\n, __FILE__, __FUNCTION__, __LINE__);device_destroy(gpio_class, MKDEV(major, 0));class_destroy(gpio_class);unregister_chrdev(major, 100ask_dht11);for (i 0; i count; i){//free_irq(gpios[i].irq, gpios[i]);//del_timer(gpios[i].key_timer);}
}/* 7. 其他完善提供设备信息自动创建设备节点 */module_init(dht11_init);
module_exit(dht11_exit);MODULE_LICENSE(GPL);
韦东山老师基于中断的驱动程序准确度太低了所以我们写个不基于中断的试试
#include linux/module.h
#include linux/kernel.h
#include linux/fs.h
#include linux/gpio.h
#include linux/delay.h
#include linux/uaccess.h #define DHT11_GPIO 115 // 假设DHT11连接到GPIO 115
#define DHT11_DATA_LEN 8 // DHT11数据长度包括温湿度值、校验和 static int dht11_gpio;
static u8 dht11_data[DHT11_DATA_LEN];static void dht11_set_gpio_output(void)
{ gpio_direction_output(dht11_gpio, 0);
} static void dht11_set_gpio_input(void)
{ gpio_direction_input(dht11_gpio);
} static int dht11_read_data(void)
{ int i, j; u8 last_state 0; // 发送开始信号 dht11_set_gpio_output(); gpio_set_value(dht11_gpio, 0); udelay(18000); gpio_set_value(dht11_gpio, 1); udelay(20); dht11_set_gpio_input(); // 等待DHT11响应 while (gpio_get_value(dht11_gpio)) { udelay(1); if (j 100) { return -1; // 超时 } } // 读取数据 for (i 0; i DHT11_DATA_LEN; i) { dht11_data[i] 0; for (j 0; j 8; j) { while (!gpio_get_value(dht11_gpio)) { udelay(1); if (j 100) { return -1; // 超时 } } udelay(40); if (!gpio_get_value(dht11_gpio)) { dht11_data[i] | (1 (7 - j)); } } } // 检查校验和 u8 sum 0; for (i 0; i DHT11_DATA_LEN - 1; i) { sum dht11_data[i]; } if (sum ! dht11_data[DHT11_DATA_LEN - 1]) { return -1; // 校验和错误 } return 0;
}
static int dht11_open(struct inode *inode, struct file *file)
{ return 0;
} static ssize_t dht11_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{ int ret; char data_str[32]; int temp_integral, temp_decimal; int humi_integral, humi_decimal; ret dht11_read_data(); if (ret 0) { return ret; } // 解析温度和湿度值 temp_integral dht11_data[2]; temp_decimal dht11_data[3]; humi_integral dht11_data[0]; humi_decimal dht11_data[1]; // 将数据转换为字符串格式 snprintf(data_str, sizeof(data_str), Temp: %d.%d C, Humidity: %d.%d %%\n, temp_integral, temp_decimal, humi_integral, humi_decimal); // 将数据复制到用户空间 if (copy_to_user(buf, data_str, strlen(data_str))) { return -EFAULT; } return strlen(data_str);
}static int dht11_release(struct inode *inode, struct file *file)
{ return 0;
} static loff_t dht11_lseek(struct file *file, loff_t offset, int whence)
{ return -EINVAL; // 不支持lseek操作
}static const struct file_operations dht11_fops { .owner THIS_MODULE, .read dht11_read, .open dht11_open, .release dht11_release, .llseek dht11_lseek,
}; static int __init dht11_init(void)
{ int ret; // 请求GPIO资源 dht11_gpio gpio_request(DHT11_GPIO, DHT11); if (dht11_gpio 0) { printk(KERN_ERR Failed to request GPIO %d\n, DHT11_GPIO); return -ENODEV; } // 导出GPIO到用户空间可选 // gpio_export(DHT11_GPIO, false); // 注册字符设备 ret register_chrdev(0, dht11, dht11_fops); if (ret 0) { printk(KERN_ERR Failed to register character device\n); gpio_free(dht11_gpio); return ret; } // 创建设备节点 ret device_create(class_create(THIS_MODULE, dht11), NULL, MKDEV(ret, 0), NULL, cebss_dht11); if (ret 0) { printk(KERN_ERR Failed to create device\n); unregister_chrdev(ret, dht11); gpio_free(dht11_gpio); return ret; } printk(KERN_INFO DHT11 driver loaded\n); return 0;
} static void __exit dht11_exit(void)
{ device_destroy(class_destroy(dht11_class), MKDEV(major, 0)); unregister_chrdev(major, dht11); gpio_free(dht11_gpio); printk(KERN_INFO DHT11 driver unloaded\n);
} module_init(dht11_init);
module_exit(dht11_exit);
MODULE_LICENSE(GPL); 不认识因为注册的时候没用变量直接给返回值拿来用了 主设备号也没对上
static int __init dht11_init(void)
{ int ret; // 请求GPIO资源 dht11_gpio gpio_request(DHT11_GPIO, DHT11); if (dht11_gpio 0) { printk(KERN_ERR Failed to request GPIO %d\n, DHT11_GPIO); return -ENODEV; } // 导出GPIO到用户空间可选 // gpio_export(DHT11_GPIO, false); // 注册字符设备 major register_chrdev(0, dht11, dht11_fops); if (major 0) { printk(KERN_ERR Failed to register character device\n); gpio_free(dht11_gpio); return ret; } gpio_class class_create(THIS_MODULE, dht11);// 创建设备节点 ret device_create(gpio_class, NULL, MKDEV(major, 0), NULL, cebss_dht11); if (ret 0) { printk(KERN_ERR Failed to create device\n); unregister_chrdev(major, dht11); gpio_free(dht11_gpio); return ret; } printk(KERN_INFO DHT11 driver loaded\n); return 0;
} static void __exit dht11_exit(void)
{ device_destroy(gpio_class, MKDEV(major, 0)); unregister_chrdev(major, dht11); gpio_free(dht11_gpio); printk(KERN_INFO DHT11 driver unloaded\n);
}
/home/book/program/cebss/driver/01_driver/06_dht11/dht11_drv.c: In function ‘dht11_read_data’: /home/book/program/cebss/driver/01_driver/06_dht11/dht11_drv.c:65:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] u8 sum 0;
这个是经典问题变量要在最开始定义
/home/book/program/cebss/driver/01_driver/06_dht11/dht11_drv.c: In function ‘dht11_init’: /home/book/program/cebss/driver/01_driver/06_dht11/dht11_drv.c:151:9: warning: assignment makes integer from pointer without a cast [-Wint-conversion] ret device_create(gpio_class, NULL, MKDEV(major, 0), NULL, cebss_dht11);
这个函数的返回值是device结构体
WARNING: __bad_udelay [/home/book/program/cebss/driver/01_driver/06_dht11/dht11_drv.ko] undefined!
这个警告是可能是因为gcc或内核不支持这个级别演延时导致的不过问题不大 查了内核源码发现好多人都用了证明是支持的所以可能是头文件包含的问题。
算了自己写一个假的好了正常要考虑架构频率进程切换等很多问题所以就简单延时一下好了
void my_udelay(unsigned long usecs)
{ unsigned long loops usecs * LOOP_PER_USEC; while(loops--);
}
[root100ask:/mnt]# insmod dht11_drv.ko [ 2587.699869] ------------[ cut here ]------------ [ 2587.711912] WARNING: CPU: 0 PID: 362 at fs/sysfs/dir.c:31 sysfs_warn_dup0x64/0x74 [ 2587.722923] sysfs: cannot create duplicate filename /class/dht11 [ 2587.731625] ---[ end trace b08c58d5eeb9152c ]--- [ 2587.739230] ------------[ cut here ]------------ [ 2587.744038] WARNING: CPU: 0 PID: 362 at lib/kobject.c:240 kobject_add_internal0x2a8/0x344 [ 2587.753533] ---[ end trace b08c58d5eeb9152d ]--- [ 2587.761908] Failed to create device insmod: ERROR: could not insert module dht11_drv.ko: File exists
和单板自带的驱动撞class名了
[root100ask:/mnt]# insmod dht11_drv.ko [ 2757.481544] Failed to request GPIO 115 insmod: ERROR: could not insert module dht11_drv.ko: No such device
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊改了一晚上啦都不好不知道咋回事算了还是用老师的代码吧
下面是我改过的最新版
#include linux/module.h
#include linux/kernel.h
#include linux/fs.h
#include linux/gpio.h
#include linux/delay.h
#include linux/uaccess.h
#include asm/io.h // 假设DHT11连接到GPIO 115
#define DHT11_GPIO 115
// DHT11数据长度包括温湿度值、校验和
#define DHT11_DATA_LEN 8
// 假设每个循环迭代需要1微秒
#define LOOP_PER_USEC 1000static int dht11_gpio;
static u8 dht11_data[DHT11_DATA_LEN];
static struct class *gpio_class;
static int major 0;void my_udelay(unsigned long usecs)
{ unsigned long loops usecs * LOOP_PER_USEC; while(loops--);
}static void dht11_set_gpio_output(void)
{ gpio_direction_output(dht11_gpio, 0);
} static void dht11_set_gpio_input(void)
{ gpio_direction_input(dht11_gpio);
} static int dht11_read_data(void)
{ int i 0, j 0;u8 sum 0; // 发送开始信号 dht11_set_gpio_output(); gpio_set_value(dht11_gpio, 0); mdelay(18); gpio_set_value(dht11_gpio, 1); my_udelay(20); dht11_set_gpio_input(); // 等待DHT11响应 while (gpio_get_value(dht11_gpio)) { my_udelay(1); if (j 100) {printk(等待响应失败\n); return -1; // 超时 } } // 读取数据 for (i 0; i DHT11_DATA_LEN; i) { dht11_data[i] 0; for (j 0; j 8; j){my_udelay(40); if (!gpio_get_value(dht11_gpio)) { dht11_data[i] | (1 (7 - j)); } } } // // 检查校验和// for (i 0; i DHT11_DATA_LEN - 1; i) { // sum dht11_data[i]; // } // if (sum ! dht11_data[DHT11_DATA_LEN - 1]) {// printk(和校验错误区\n);// return -1; // 校验和错误 // } return 0;
}
static int dht11_open(struct inode *inode, struct file *file)
{ return 0;
} static ssize_t dht11_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{ int ret; char data_str[32]; int temp_integral, temp_decimal; int humi_integral, humi_decimal; ret dht11_read_data(); if (ret 0) { return ret; } // 解析温度和湿度值 temp_integral dht11_data[2]; temp_decimal dht11_data[3]; humi_integral dht11_data[0]; humi_decimal dht11_data[1]; // 将数据转换为字符串格式 snprintf(data_str, sizeof(data_str), %3d %2d\n, temp_integral, humi_integral); printk(%s\n, data_str);// 将数据复制到用户空间 if (copy_to_user(buf, data_str, 6)) { return -EFAULT; } return strlen(data_str);
}static int dht11_release(struct inode *inode, struct file *file)
{ return 0;
} static loff_t dht11_lseek(struct file *file, loff_t offset, int whence)
{ return -EINVAL; // 不支持lseek操作
}static const struct file_operations dht11_fops { .owner THIS_MODULE, .read dht11_read, .open dht11_open, .release dht11_release, .llseek dht11_lseek,
}; static int __init dht11_init(void)
{// 请求GPIO资源 // dht11_gpio gpio_request(DHT11_GPIO, DHT11); // if (dht11_gpio 0) { // printk(KERN_ERR Failed to request GPIO %d\n, DHT11_GPIO); // return -ENODEV; // } // 导出GPIO到用户空间可选 // gpio_export(DHT11_GPIO, false); // 注册字符设备 major register_chrdev(0, dht11, dht11_fops); if (major 0) { printk(KERN_ERR Failed to register character device\n); gpio_free(dht11_gpio);return major; } gpio_class class_create(THIS_MODULE, dht11);// 创建设备节点 device_create(gpio_class, NULL, MKDEV(major, 0), NULL, cebss_dht11); if (IS_ERR(gpio_class)) { printk(KERN_ERR Failed to create device\n); unregister_chrdev(major, dht11); gpio_free(dht11_gpio); return PTR_ERR(gpio_class); } printk(KERN_INFO DHT11 driver loaded\n); return 0;
} static void __exit dht11_exit(void)
{ device_destroy(gpio_class, MKDEV(major, 0));class_destroy(gpio_class); unregister_chrdev(major, dht11); gpio_free(dht11_gpio);printk(KERN_INFO DHT11 driver unloaded\n);
} module_init(dht11_init);
module_exit(dht11_exit);
MODULE_LICENSE(GPL);
最后挣扎一下
试试内核中的dht11程序 也是不行啊没办法单核cpu这中持续采集就是没法很准确就这样吧。哎
6、 展示