一. 项目要求
下面表格是我项目中需要用到的硬件和功能,我们接下来会一个一个完成其功能。
引脚/硬件 | 设置 | 目的 |
PWM0/PD16 | pwm信号(0-2,5KHz) | 控制亮度 |
PG15 | GPIO输出 | 控制风机 |
UART1_RX/PD22,UART1_TX//PD21 | 串口1 | 读co2传感器 |
UART3_RX/PD11,UART3_TX/PD10 | 串口3 | 读485传感器 |
PD20 | GPIO输出 | 控制485读写模式 |
PD9 | GPIO输入,上拉 | 读上限位 |
PD7 | GPIO输入,上拉 | 读下限位 |
PE12 | GPIO输入,上拉 | 读水位 |
PE16 | GPIO输出 | 控制继电器,来控制压缩机 |
PE15 | GPIO输出 | 控制继电器,来控制水泵 |
PD6 | GPIO输入,上拉 | 中间限位 |
PD8 | GPIO输出 | 控制继电器,底盘上升 |
PD18 | GPIO输出 | 控制继电器,底盘下降 |
PD19 | GPIO输出 | 控制固态继电器,来控制水加热(已接220v) |
双通道DSI | 屏幕显示 | |
USB摄像头 | 获取图像 |
二. PWM0/PD16
pwm信号(0-2,5KHz)
2.1 源码结构说明
本模块借助于标准 Linux PWM 子系统。其代码路径为:
tina/lichee/linux-5.4/drivers/pwm/pwm-sunxi-group.c
2.2 模块配置说明
2.2.1 内核配置
在 tina 根目录下,执行 make kernel_menuconfig,进行内核驱动的配置
在 tina 根目录下,执行 make kernel_menuconfig,进行内核驱动的配置
在 tina 根目录下,执行 make kernel_menuconfig,进行内核驱动的配置
2.2.1.1 pwm-sunxi-group.c
Device Drivers
└─>Pulse-Width Modulation (PWM) Support
└─>SUNXI PWM SELECT.
└─>Sunxi PWM group support
2.2.2 dts 配置
通过命令 cdts 可以跳转到方案 dts 的路径。分享dts路径:
itna/lichee/linux-5.4/arch/riscv/boot/dts/sunxi/sun20iw1p1.dtsi
pwm 配置如下:
pwm: pwm@2000c00 {
#pwm-cells = <0x3>;
compatible = "allwinner,sunxi-pwm";
reg = <0x0 0x02000c00 0x0 0x3ff>;
clocks = <&ccu CLK_BUS_PWM>;
resets = <&ccu RST_BUS_PWM>;
pwm-number = <8>;
pwm-base = <0x0>;
sunxi-pwms = <&pwm0>, <&pwm1>, <&pwm2>, <&pwm3>, <&pwm4>,
<&pwm5>, <&pwm6>, <&pwm7>;
};
pwm0: pwm0@2000c10 {
compatible = "allwinner,sunxi-pwm0";
reg = <0x0 0x02000c10 0x0 0x4>;
reg_base = <0x02000c00>;
};
pwm1: pwm1@2000c11 {
compatible = "allwinner,sunxi-pwm1";
reg = <0x0 0x02000c11 0x0 0x4>;
reg_base = <0x02000c00>;
};
pwm2: pwm2@2000c12 {
compatible = "allwinner,sunxi-pwm2";
reg = <0x0 0x02000c12 0x0 0x4>;
reg_base = <0x02000c00>;
};
pwm3: pwm3@2000c13 {
compatible = "allwinner,sunxi-pwm3";
reg = <0x0 0x02000c13 0x0 0x4>;
reg_base = <0x02000c00>;
};
pwm4: pwm4@2000c14 {
compatible = "allwinner,sunxi-pwm4";
reg = <0x0 0x02000c14 0x0 0x4>;
reg_base = <0x02000c00>;
};
pwm5: pwm5@2000c15 {
compatible = "allwinner,sunxi-pwm5";
reg = <0x0 0x02000c15 0x0 0x4>;
reg_base = <0x02000c00>;
};
pwm6: pwm6@2000c16 {
compatible = "allwinner,sunxi-pwm6";
reg = <0x0 0x02000c16 0x0 0x4>;
reg_base = <0x02000c00>;
};
pwm7: pwm7@2000c17 {
compatible = "allwinner,sunxi-pwm7";
reg = <0x0 0x02000c17 0x0 0x4>;
reg_base = <0x02000c00>;
};
板级 dts 主要是配置 pwm 的引脚设置,通过 cconfigs 可以跳转到板级 dts 的路径下:
tina/device/config/chips/d1/configs/nezha/linux/board.dts
board.dts 配置如下所示:
&pio {
...............//省略其他模块的引脚设置
pwm0_pin_a: pwm0@0 {
pins = "PD16";
function = "pwm0";
drive-strength = <10>;
bias-pull-up;
};
pwm0_pin_b: pwm0@1 {
pins = "PD16";
function = "gpio_in";
bias-disable;
};
pwm2_pin_a: pwm2@0 {
pins = "PD18";
function = "pwm2";
drive-strength = <10>;
bias-pull-up;
};
pwm2_pin_b: pwm2@1 {
pins = "PD18";
function = "gpio_in";
};
pwm7_pin_a: pwm7@0 {
pins = "PD22";
function = "pwm7";
drive-strength = <10>;
bias-pull-up;
};
pwm7_pin_b: pwm7@1 {
pins = "PD22";
function = "gpio_in";
};
...............//省略其他模块的引脚设置
};
&pwm0 {
pinctrl-names = "active", "sleep";
pinctrl-0 = <&pwm0_pin_a>;
pinctrl-1 = <&pwm0_pin_b>;
status = "okay";
};
&pwm2 {
pinctrl-names = "active", "sleep";
pinctrl-0 = <&pwm2_pin_a>;
pinctrl-1 = <&pwm2_pin_b>;
status = "okay";
};
&pwm7 {
pinctrl-names = "active", "sleep";
pinctrl-0 = <&pwm7_pin_a>;
pinctrl-1 = <&pwm7_pin_b>;
status = "okay";
}
一般方案的dts已经配置完成,想要使用pwm的时候只需在board.dts 配置好 pwm 通路以及对应的引脚,即可使用
2.3 驱动层使用说明
按照以下接口使用
1.pwm_request: 申请pwm句柄
2.pwm_config: 配置pwm period & duty,注意单位是ns
3.pwm_set_polarity: 设置pwm的极性
4.pwm_enable: 使能pwm
不使用
1.pwm_di代码sable: 关闭pwm
2.pwm_free: 释放pwm句柄
2.4 应用层使用说明
相关调试节点一般在/sys/class/pwm 目录下,它创建了一个 pwmchip,对应 CPUX 上面的 pwm 功能:
root@TinaLinux:/sys/class/pwm#
ls pwmchip0
要使用 pwm,例如使用 CPUX 的 pwm0, 则按如下操作,生成 pwm0 目录:
root@TinaLinux:/# echo 0 > /sys/class/pwm/pwmchip0/export
root@TinaLinux:/# ls /sys/class/pwm/pwmchip0/pwm0/
capture enable polarity uevent
duty_cycle period power
通过新增的 pwm0 目录下的节点来设置 pwm:
节点 | 介绍 |
---|---|
period | 表示 pwm 的周期,单位 ns |
duty_cycle | 表示占空比,单位 ns |
enable | 表示是否使能 pwm |
polarity | 表示 pwm 极性 (normal/inversed) |
使能 pwm 操作节点顺序可如下所示:
• period 可通过 “echo N > period” 写入数据,修改频率;
• duty_cycle 可以通过 “echo N > duty_cycle 写入数据,修改占空比”;
• 最后,“echo 1 > enable” 来使能该通道的 pwm。
通过 cat 以下节点,可查看 pwm 使用情况:
root@TinaLinux:/# cat sys/kernel/debug/pwm
platform/7020c00.s_pwm, 1 PWM device
pwm-0 ((null) ): period: 0 ns duty: 0 ns polarity: normal
platform/300a000.pwm, 2 PWM devices
pwm-0 (sysfs ): requested period: 0 ns duty: 0 ns polarity: normal
pwm-1 ((null) ): period: 0 ns duty: 0 ns polarity: normal
通过编写代码来操作 pwm:操作 pwm 的节点与上述的节点一样,不过操作的方式变成了:编写代码 open/fopen 打开 pwm 节点,write/fwrite 来向 pwm 节点写入数据等等。 简单的示例如下所示:
int pwm_setup()
{
int ret, fd;
fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY);
if (fd < 0) {
dbmsg("open export failed\n");
return -1;
}
ret = write(fd, "0", strlen("0"));
if(ret < 0) {
dbmsg ("creat pwm0 error\n");
return -1;
}
return 0;
}