之前做了一个GPIO模式下的LED驱动,由于是按I2C总线分组设置LED的,所以在实际应用中是不够的,这次根据文档完成了LED模式下的LED驱动,及单个灯可控驱动。
根据文档可知,配置13H寄存器为0即可设P1_7-P1_0为LED模式。
而LED模式下的控制相对GPIO模式要简单的多,只需要对每个口连接的灯设置颜色即可,这里的颜色是如下图对应的颜色,分为256个级别,及红黄蓝各有256个级别;
例如P1_0口接的是红灯,而P1_1接的是绿,P1_2接的是蓝,则如需要显示红色则对节点传入ff0000即可。
代码如下:
static void switch_to_led_mode()
{
//配置成LED模式
char buffer[LED_REG_LEN];
int ret = 0;
printk("in:%s, line:%d\n", __func__, __LINE__);
buffer[0] = 0x12; //AW9523B register P0 address
buffer[1] = 0x00; //0x1101 1011
ret = led_tx8_data(this_client, &buffer[0], 2);
ret = led_rx_data(this_client, &buffer[0], 1);
buffer[0] = 0x13; //AW9523B register P1 address
buffer[1] = 0x00; //0x1110 0110
ret = led_tx8_data(this_client, &buffer[0], 2);
ret = led_rx_data(this_client, &buffer[0], 1);
printk("in:%s, line:%d\n", __func__, __LINE__);
}
由于之前代码太凌乱,所以由带头大哥帮忙整理了下代码,瞬间把我秒成渣了。
SYS节点注册:
#define CREATE_SYSFS_LED(obj,_name,_port) \
{\
ret = sysfs_create_file(obj, &dev_attr_##_name##_port.attr);\
if (ret) {\
printk(KERN_ERR "i2c0_led_sysfs_init:" "sysfs_create_group failed\n");\
goto err4;\
}\
}
static int i2c0_led_sysfs_init(void)
{
int ret ;
led_kobj = kobject_create_and_add("android_i2c0_led", NULL);
if (led_kobj == NULL) {
printk(KERN_ERR
"i2c0_led_sysfs_init:"\
"subsystem_register failed\n");
ret = -ENOMEM;
goto err;
}
CREATE_SYSFS_LED(led_kobj, led, 2);
CREATE_SYSFS_LED(led_kobj, led, 3);
CREATE_SYSFS_LED(led_kobj, led, 4);
CREATE_SYSFS_LED(led_kobj, led, 5);
CREATE_SYSFS_LED(led_kobj, led, 6);
printk("i2c_led0_sysfs_init ++++++++++++++++\n");
return 0 ;
err4:
kobject_del(led_kobj);
err:
return ret ;
}
DEVICE_ATTR show和store函数:
//将传入的要显示的颜色值分别出红绿蓝对应的值
static void int_convert_to_color_t(int value,unsigned char *red,unsigned char *green,unsigned char * blue)
{
*blue=value&0xFF;
value=value/256;
*green=value&0xFF;
value=value/256;
*red=value&0xFF;
}
static ssize_t led_store(struct device *dev,
struct device_attribute *attr,const char *buf, size_t count,int port)
{
unsigned char red;
unsigned char green;
unsigned char blue;
int color;
if(port> LED_MAX)
return -1;
printk("set led =%d color=%s \n",port,buf);
#if 1
sscanf(buf, "%du", &color);
int_convert_to_color_t(color,&red,&green,&blue);
all_led[port].color.red=red;
all_led[port].color.green=green;
all_led[port].color.blue=blue;
set_led_color(all_led[port]);
printk("ok red=%d green=%d blue=%d \n",red,green,blue);
#endif
return count;
}
static ssize_t led_show(struct device *dev,
struct device_attribute *attr, char *buf,int port)
{
int red_value = 0, green_value = 0, blue_value = 0;
ssize_t ret = 0;
printk("cat debug buf++++++++++++++++++++++++++++++++++++=\n");
red_value = all_led[port].color.red;
green_value = all_led[port].color.green;
blue_value = all_led[port].color.blue;
ret = red_value * 256 * 256 + green_value * 256 + blue_value;
printk("++++++ret = %d\n++++++", ret);
sprintf(buf, "ret = %d\n", ret);
ret = strlen(buf) + 1;
return ret;
}
#define LED_DEVICE_ATTR(name_,_port) \
static ssize_t led_show_##_port(struct device *dev, \
struct device_attribute *attr, char *buf) \
{\
return led_show(dev,attr,buf,_port);\
}\
static ssize_t led_store_##_port(struct device *dev,\
struct device_attribute *attr,const char *buf, size_t count)\
{\
return led_store(dev,attr,buf,count,_port);\
}\
static DEVICE_ATTR(name_##_port, 0666,led_show_##_port, led_store_##_port);
LED_DEVICE_ATTR(led, 2)
LED_DEVICE_ATTR(led, 3)
LED_DEVICE_ATTR(led, 4)
LED_DEVICE_ATTR(led, 5)
LED_DEVICE_ATTR(led, 6)
设置灯口以及灯口对应的颜色值:
typedef struct{
unsigned char red;
unsigned char green;
unsigned char blue;
}rgb_reg_t;
typedef struct{
unsigned char red;
unsigned char green;
unsigned char blue;
}color_t;
typedef struct{
rgb_reg_t reg;
color_t color;
}led_t;
static void set_led_RGB(unsigned char reg,unsigned char data)
{
char buffer[LED_REG_LEN];
buffer[0]=reg;
buffer[1]=data;
//buffer[0]是寄存器地址,buffer[1]是传入的数据
led_tx8_data(this_client, &buffer[0], 2);
led_rx_data(this_client, &buffer[0], 1);
}
static void set_led_color(led_t led)
{
set_led_RGB(led.reg.red,led.color.red);
set_led_RGB(led.reg.green,led.color.green);
set_led_RGB(led.reg.blue,led.color.blue);
}
static void init_all_led()
{
//led 6
all_led[LED_6].reg.red = GPIO_P1_4;
all_led[LED_6].reg.green = GPIO_P1_5;
all_led[LED_6].reg.blue = GPIO_P1_6;
//led 5
all_led[LED_5].reg.red = GPIO_P0_5;
all_led[LED_5].reg.green = GPIO_P0_6;
all_led[LED_5].reg.blue = GPIO_P0_7;
//led 4
all_led[LED_4].reg.red = GPIO_P0_2;
all_led[LED_4].reg.green = GPIO_P0_3;
all_led[LED_4].reg.blue = GPIO_P0_4;
//led 3
all_led[LED_3].reg.red = GPIO_P1_3;
all_led[LED_3].reg.green = GPIO_P0_0;
all_led[LED_3].reg.blue = GPIO_P0_1;
//led 2
all_led[LED_2].reg.red = GPIO_P1_0;
all_led[LED_2].reg.green = GPIO_P1_1;
all_led[LED_2].reg.blue = GPIO_P1_2;
}
于是乎,原本杂乱不堪的代码,瞬间就高大上了啊,哈哈~