番外篇——直流电机桥源码分析&LED驱动例程开发

直流电机桥测试代码分析

#define DCM_IOCTRL_SETPWM	(0x10)
#define DCM_IOCTRL_STATUS	(0x20)
#define DCM_IOCTRL_STOP		(0x30)
#define DCM_IOCTRL_START	(0x40)

定义了对设备的操作命令,类似于枚举类型。在驱动中也同样有所定义。

char *DCM_DEV="/dev/DCMotor";

声明了设备在系统中注册的名字,和驱动要一一对应,在系统中设备统一放在/dev/文件夹下面。

ioctl(dcm_fd, cmd, arg);

调用驱动中定义的函数,对设备进行操作,dcm_fd是设备的节点,cmd是之前定义过操作的类型,arg是对应的参数。

如果仔细阅读,还会发现在主函数中定义的status变量从来没有使用,可以删除。

直流电机桥驱动代码分析

module_init(uptech_dcm_init);
module_exit(uptech_dcm_exit);

在字符型驱动开发中,我们已经讲过,上面两个函数分别是加载驱动和卸载驱动所执行的函数。

#define DEVICE_NAME     "DCMotor"
#define DEV_MAJOR        0

驱动中同样定义了设备名称,DEV_MAJOR用于模块被加载时初始化函数调用的创建节点函数,为0表示自动获取设备号。

pwm_request(0, "my_pwm0");
pwm_config(pwm0, 10000000, 100000000);
pwm_disable(pwm0);
pwm_enable(pwm0);

pwm在linux中提供了很多api,pwm_request是申请pwm设备,第一个参数是i.MX6内置的pwmID号,从0到3一共4个,第二个参数是对此设备的简称。

pwm_config是配置pwm设备,第一个参数是pwm设备,第二个参数是一个周期内,高电平的时间,单位是纳秒,第三个参数是周期的长度,单位也是纳秒,在本例中,pwm0对应的引脚将以100000000纳秒为周期,其中前10000000纳秒为高电平,剩余时间都为低电平,对于电机来说,高电平转,低电平不转,但是由于惯性,电机仍有旋转趋势,控制占空比(高电平占周期的时间比)即可控制转速,占空比越大,转速越快。

pwm_disable是关闭pwm设备,停止pwm信号的作用,相反,pwm_enable是使能pwm设备,开始pwm信号,两个函数的参数都是pwm设备。

仿写HBLED驱动程序

为了不和直流电机桥已有的引脚冲突,我们选择pwmID为2的设备作为LED的Signal引脚。HBLED的性能如下。

  1. 需要5V或3.3V供电。
  2. 需要GND引脚接地。
  3. Signal引脚高电平时灯亮,低电平时灯灭。

利用芯片手册修改设备树

接下来我们打开i.MX6的芯片手册,位于/01 创新创客智能硬件平台光盘资料/创新创客智能硬件平台光盘V1.0/04_硬件/0401_数据手册/13_Cortex-A 系列核心板/IMX6/IMX6SDLRM.pdf,搜索pwm3(芯片手册中定义id为1到4,在linux中申请的id为0到3)。

在这里插入图片描述
可以看见SW_PAD_CTL_PAD_SD1_DAT1引脚可以用于PWM3_OUT功能。

接下来修改设备树,在虚拟机终端中输入sudo nano /home/uptech/fsl-6dl-source/kernel-3.14.28/arch/arm/boot/dts/imx6qdl-sabresd.dtsi

在这里插入图片描述

发现此引脚已经被复用为GPIO,将此引脚注释掉。

在这里插入图片描述
找到后面定义pwm引脚复用的地方,在后面添加以下代码。

pinctrl_pwm3: pwm3grp {
        fsl,pins = <
                MX6QDL_PAD_SD1_DAT1__PWM3_OUT           0x1b0b1
        >;
};

在这里插入图片描述
找到pwm定义的位置,在后面添加pwm3的定义。

&pwm3 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_pwm3>;
        status = "okay";
};

在这里插入图片描述
如果读者想深入了解0x1b0b1、MX6QDL_PAD_SD1_DAT1__PWM3_OUT等写法的原因,可以前往文件资料中/01 创新创客智能硬件平台光盘资料/创新创客智能硬件平台光盘V1.0/03_系统/0301_Linux/03_linux系统移植/01_doc/03_i.MX6-魔法师inux系统实验指导书V2.2.pdf的第四章继续学习。简单来说前者是引脚复用寄存器的配置,可以在芯片手册中查到,后者是引脚复用后的专用名称,可以在pinfunc.h中找到。

修改完设备树需要重新编译内核和设备树文件,然后重新烧录系统。

利用原理图寻找引脚

打开文件资料中/01 创新创客智能硬件平台光盘资料/创新创客智能硬件平台光盘V1.0/04_硬件/0402_原理图/12_Cortex-A 系列核心板与底板 文件夹内的i.MX6 核心板 V1.2.pdf和魔法师Cortex-A系列底板 V1.3.pdf。

在核心板的原理图中搜索SD1_DAT1,可以看到SD1_DAT1对应的是CSI0 RST B。
在这里插入图片描述
打开底板原理图,搜索CSI0 RST B,可以看到对应了J5端口的20号引脚,说明我们LED的signal需要插在此引脚上。
在这里插入图片描述

仿写代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/pwm.h>
#include <linux/fs.h>

#define DEVICE_NAME     "HBLED"
#define DEV_MAJOR        0

#define DRIVER_AUTHOR	"sertonry@obcube.cn"
#define DRIVER_DESCRIPTION "Unknown_HighBrightnessLED"

#define HBLED_IOCTRL_SETPWM	(0x10)
#define HBLED_IOCTRL_OFF	(0x20)
#define HBLED_IOCTRL_ON		(0x30)

static struct cdev hbLEDcDev;
struct class* hbLEDclass;
dev_t devNo;

struct pwm_device* pwm;
static int defaultPWMRate = 50;

static long HBLED_ioctl(struct file* filp, unsigned int cmd, unsigned long arg)
{
	switch (cmd) {
	case HBLED_IOCTRL_SETPWM:
		if (arg > 100 || arg < 0)
		{
			printk("HBLED_IOCTRL_SETPWM arg can't is %ld!\n", arg);
			break;
		}
		pwm_enable(pwm);
		pwm_config(pwm, 20000 * arg, 2000000);
		break;
	case HBLED_IOCTRL_OFF:
		pwm_config(pwm, 20000 * 0, 2000000);
		pwm_disable(pwm);
		break;
	case HBLED_IOCTRL_ON:
		pwm_enable(pwm);
		break;
	}
	return 0;
}

static struct file_operations HBLED_gpio_fops = {
	.owner = THIS_MODULE,
	.unlocked_ioctl = HBLED_ioctl,
};

static int create_dev_node(void)
{
	int ret;
	
	if (DEV_MAJOR)
	{
		devNo = MKDEV(DEV_MAJOR, 0);
		ret = register_chrdev_region(devNo, 1, DEVICE_NAME);
	}
	else {
		ret = alloc_chrdev_region(&devNo, 0, 1, DEVICE_NAME);
	}
	if (0 < ret) {
		return ret;
	}
	
	cdev_init(&hbLEDcDev, &HBLED_gpio_fops);
	ret = cdev_add(&hbLEDcDev, devNo, 1);
	if (ret) {
		printk("cdev_add(); failed! ret_num=%d\n", ret);
	}
	hbLEDclass = class_create(THIS_MODULE, DEVICE_NAME);
	if (IS_ERR(hbLEDclass)) {
		printk("Err: failed in creating class.\n");
		return -1;
	}
	device_create(hbLEDclass, NULL, devNo, NULL, DEVICE_NAME);
	return 0;
}

int __init HBLED_init(void)
{
	int ret;
	pwm = pwm_request(2, "hbLEDpwm");		
	if (IS_ERR(pwm)) {
		printk("ERROR is %ld\n", PTR_ERR(pwm));
		return -1;
	}
	pwm_config(pwm, 20000 * defaultPWMRate, 2000000);

	ret = create_dev_node();
	if (ret)
		return ret;
	return 0;
}

void __exit HBLED_exit(void)
{
	pwm_disable(pwm);               
	pwm_free(pwm);                  

	cdev_del(&hbLEDcDev);
	device_destroy(hbLEDclass, devNo);
	class_destroy(hbLEDclass);

	unregister_chrdev_region(devNo, 1);
}
module_init(HBLED_init);
module_exit(HBLED_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESCRIPTION);

对应的Makefile文件如下

obj-m	:=HighBrightnessLED_driver.o

KERNELDIR := /home/uptech/fsl-6dl-source/kernel-3.14.28/
PWD := $(shell pwd)

all:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) clean

仿写HBLED测试程序

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>

#define HBLED_IOCTRL_SETPWM	(0x10)
#define HBLED_IOCTRL_OFF	(0x20)
#define HBLED_IOCTRL_ON		(0x30)

char* HBLED_DEV = "/dev/HBLED";		
int cmd_group[] = { HBLED_IOCTRL_SETPWM, HBLED_IOCTRL_ON, HBLED_IOCTRL_OFF };

void print_menu()
{
	printf("-----HBLED_TEST-----\n");
	printf("|   1.SETPWM      |\n");
	printf("|   2.ON          |\n");
	printf("|   3.OFF         |\n");
	printf("|   4.EXIT        |\n");
	printf("-------------------\n");
}

int main(void)
{
	int hbled_fd, menu_num, cmd, arg;
	hbled_fd = open(HBLED_DEV, O_WRONLY);			
	if (hbled_fd < 0) {
		printf("Error opening %s device\n", HBLED_DEV);
		return 1;
	}
	while (1)
	{
		print_menu();
		
		scanf("%d", &menu_num);
		
		if (menu_num == 4)
			break;
		
		if (menu_num == 1)
		{
			printf("Input brightness value(0~100)\n");
			scanf("%d", &arg);
			if (arg > 100 || arg < 0)
			{
				printf("Brightness can't be %ld!\n", arg);
				continue;
			}
		}
		
		cmd = cmd_group[menu_num - 1];
		ioctl(hbled_fd, cmd, arg);
	}
	close(hbled_fd);						
	return 0;
}

对应的Makefile文件如下

CC = arm-poky-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/opt/poky/1.7/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi
TARGET = HighBrightnessLED_test
all:
	$(CC) -o $(TARGET) $(TARGET).c 
clean:
	rm $(TARGET)

实际测试

在这里插入图片描述
亮度为0
在这里插入图片描述

亮度为5%
在这里插入图片描述

亮度为50%
在这里插入图片描述

亮度为100%
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用MSP430F5529的库函数来实现PWM驱动直流电程。首先,您可以利用定时器A来生成PWM信号。您可以参考MSP430F5529 DriverLib库函数学习笔记中的定时器A部分,了解如何使用定时器A来生成PWM信号\[1\]。另,您还可以参考MSP430F5529库函数定时器A——硬件PWM的程,了解如何在实际操作中使用库函数来实现PWM驱动\[1\]。 在设置GPIO引脚的驱动能力方面,您可以使用GPIO_setDriveStrength函数来设置引脚的驱动能力。如,如果您想将P1.0设置为强驱动,您可以使用以下代码\[2\]: GPIO_setDriveStrength(GPIO_PORT_P1, GPIO_PIN0, GPIO_FULL_OUTPUT_DRIVE_STRENGTH); 默认情况下,系统将引脚的驱动能力设置为弱驱动。如果您想修改引脚的驱动能力,您可以使用GPIO_REDUCED_OUTPUT_DRIVE_STRENGTH和GPIO_FULL_OUTPUT_DRIVE_STRENGTH参数来设置引脚的驱动能力为弱驱动或强驱动\[3\]。 综上所述,您可以使用MSP430F5529的库函数来实现PWM驱动直流电程。您可以参考MSP430F5529 DriverLib库函数学习笔记和MSP430F5529库函数定时器A——硬件PWM的程来了解如何使用库函数来生成PWM信号和设置引脚的驱动能力。 #### 引用[.reference_title] - *1* [MSP430F5529库函数定时器A——捕获实验](https://blog.csdn.net/qq_63922192/article/details/127779050)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [MSP430F5529库函数GPIO学习](https://blog.csdn.net/qq_63922192/article/details/127673982)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值