|
《小试》根据cpu温度控制风扇转速
发表于 2015-5-12 14:15:01
浏览:45723
|
回复:27
打印
只看该作者
[复制链接]
楼主
本帖最后由 madman 于 2015-5-12 14:15 编辑
之前刚拿到的板,搭建好基本的环境之后就想着进一步学习一下,不过限于初学者能力有限,不知道做什么好。后面在论坛乱逛无意间看到一个根据cpu温度控制风扇开关的应用,觉得挺有意思的。不过这个应用只是测到温度使用io口控制开关。然后我就想着使用pwm达到平时我们电脑散热风扇的那种效果,然后以此对驱动进行学习。然后就有下面那么个东西~~
首先我使用的是官方默认板的Android SDK ,然后对它进行了编译。其后我主要是修改了kernel中原来的驱动,然后给上层留了个接口作为开关,测量温度和控制pwm都在驱动中完成了。额。。还有就是原带的风扇是不带pwm的接口的,这也让我郁闷了下,然后使用了个简单的三极管开关电路把pwm接口加了进去。然后根据之前看到的帖子,我们可以cat板子上的sys/class/hwmon/hwmon0/device/temp0_input,然后它就会打印出温度。根据这个文件夹我找到了它对应的驱动,在sdk里的kernel/drivers/hwmon/rockchip-hwmon.c里。然后我就对rockchip-hwmon.c这个驱动进行了小小的添加。这个驱动里上层的接口函数是show_input,然后我复制了这个函数并把它的return buf部分去掉,然后把他定义成了外部函数,这样就可以在别的驱动里调用它读取温度。至于pwm,我是在原来的背光pwm里修改的。背光驱动在kernel/drivers/video/backlight/pwm_bl.c上。首先这是背光的dts,添加进kernel/ arch/arm/boot/dts/rk3288.dtsi里面就可以了
backlight {
compatible = "pwm-backlight";
pwms = <&pwm1 0 10000>;//0 10000
rockchip,pwm_id= <1>;
brightness-levels = <214 213 212 211 210 209 208 207 206 205 204 203 202 201 200 199 198 197 196 195 194 193 192 191 190 189 188 187 186 185 184 183 182 181 180 179 178 177 176 175 174 173 172 171 170>;
default-brightness-level = <180>;//180
enable-gpios = <&gpio8 GPIO_A6 GPIO_ACTIVE_HIGH>;
};
至于控制pwm占空比使用的是这个函数pwm_config(&w_pwm, 1000, 10000);至于功能的实现我使用了一个线程在线程里每隔一秒读取一次温度然后调整对应的pwm。原来使用的是定时器,然后发现定时器不能带参数,带了就崩溃~_~..最后使用proc_create创建了个简单的读写接口给上层调用控制开和关。
好吧,大概就是这样,也不罗嗦了,下面是相关的图和部分代码
rockchip-hwmon.c
extern int show_input_pwm(struct device *dev,
struct device_attribute *devattr)//显示温度功能的实现
{
int temp;
struct rockchip_temp *data = dev_get_drvdata(dev);//获取数据
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
u8 tsadc_addr = data->tsadc_addr[attr->index];
temp = data->ops.read_sensor(tsadc_addr);
hwmon_cpu_wendu = temp;
return 0;
}
extern void show_cpu(void)
{
show_input_pwm(&(fpdev->dev),&sensor_dev_attr_temp0_input.dev_attr);
}
pwm_bl.c
int func(void* data)
{
int high_pwm;
while(1)
{
if( kthread_should_stop()) return -1;
show_cpu();
printk("%d\n",hwmon_cpu_wendu);
if(hwmon_cpu_wendu > 0 )
{
if(hwmon_cpu_wendu <= 40)
pwm_config(&w_pwm, 100, 10000);
else if((hwmon_cpu_wendu>40)||(hwmon_cpu_wendu<80))
{
high_pwm = hwmon_cpu_wendu*125;
pwm_config(&w_pwm, high_pwm, 10000);
}
else if(hwmon_cpu_wendu >= 80)
pwm_config(&w_pwm, 9800, 10000);
}
printk(KERN_ALERT "func running\n");
set_current_state(TASK_UNINTERRUPTIBLE); //设置进程的状态
schedule_timeout(1*HZ); //在指定的时间到期后(timeout了)将进程唤醒
if(out_pthread == 1)//退出
{
pwm_config(&w_pwm, 100, 10000);
break;
}
}
return 0;
}
probe里:
proc_create("pwm",0666,NULL,&proc_fops);
msg=kmalloc(GFP_KERNEL,FANBUFSIZE*sizeof(char));
w_pwm = *(pb->pwm);
mytask=kthread_create(func,0,"mykthread");
wake_up_process(mytask);
之后的话进一步会将pwm的驱动从背光里单独拿出来,做成一个单独的驱动
pwm.zip
(14.44 KB, 下载次数: 106)
|
|