1. 程式人生 > >RK3188&AW9523B I2C介面LED驅動(2)

RK3188&AW9523B I2C介面LED驅動(2)

之前做了一個GPIO模式下的LED驅動,由於是按I2C匯流排分組設定LED的,所以在實際應用中是不夠的,這次根據文件完成了LED模式下的LED驅動,及單個燈可控驅動。
根據文件可知,配置13H暫存器為0即可設P1_7-P1_0為LED模式。
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;
}

於是乎,原本雜亂不堪的程式碼,瞬間就高大上了啊,哈哈~