瑞昱rtl8762芯片通过I2C操作AW20108,从而实现多个LED的控制
瑞昱rtl8762芯片通过I2C操作AW20108,从而实现多个LED的控制
- 1、引脚分布
- 2、了解AW20108
- 1)了解IC引脚
- 2)如何控制
- a、通信方式
- b、如何点亮LED
- 3、代码添加
- 1)引脚宏定义
- 2)初始化GPIO
- 3)配置I2C结构体
- 4)初始化及控制
- 4、总结
本人还在学习、摸索rtl8762,如有错误之处,欢迎指出。
1、引脚分布
| 引脚名称 | 引脚编号 |
|---|---|
| SCK | P3_2 |
| DATA | P3_3 |
| INTN | P2_2 |
| EN | P0_2 |
2、了解AW20108
资料来源:艾为官方,有需要的同学可以自取。
1)了解IC引脚
从下图可以看到,需要通过软件控制的IO口有4根,分别是:SDA、SCL、INTN、EN。硬件上目前是将EN直接拉高,所以EN不需要操作。

2)如何控制
a、通信方式
aw20108是通过I2C控制,最大速率为400khz。器件地址通过由第25pin AD选择,硬件上与GND连接,所以器件地址为0x3A(如下图所示),大家根据自身硬件连接修改器件地址。

b、如何点亮LED
aw20108可以同时控制108颗LED,而它是通过扫描控制。那么作为程序员,应该如何点亮LED呢?其实很简单,数据手册给出了两种方案:
1、将ALLON位置1,通过改变某个LED的电流来点亮LED;
2、将所有LED电流设为非0值(即有电流),再通过控制寄存器LEDONx来点亮LED;
两种方式各有优点:
第一种:代码量略多,可以单独控制某个LED,从而不影响别的LED状态;
第二种:代码量少,编写方便。由于一个寄存器LEDONx中,包含6个LED的状态,同时LEDONx是只写的,如果想做到点亮LED0的同时,不影响LED1的话,只能代码上使用变量保存寄存器的值。
所以,目前代码实现上使用的是第一种操作方式,以下代码也会以第一种方式展现。
3、代码添加
1)引脚宏定义
/***************************** IIC *****************************/
#define I2C_CLK_PIN P3_2 //< I2C 时钟线
#define I2C_DATA_PIN P3_3 //< I2C 数据线/************************** LED DRIVER **************************/
#define LED_DRIVER_I2C I2C0
#define LED_INTN_PIN P2_2
#define LED_EN_PIN P0_2 //< led驱动使能
#define LED_INTN_PIN_NUM GPIO_GetPin(LED_INTN_PIN)
#define LED_EN_PIN_NUM GPIO_GetPin(LED_EN_PIN)
2)初始化GPIO
初始化GPIO分为两组,1组为spi的引脚初始化,1组为普通IO的引脚初始化。
/*** @brief :引脚初始化* @param :NULL* @retval :NULL*/
static void gpio_init(void)
{RCC_PeriphClockCmd(APBPeriph_GPIO, APBPeriph_GPIO_CLOCK, ENABLE);Pad_Config(I2C_CLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP,PAD_OUT_ENABLE, PAD_OUT_HIGH);Pad_Config(I2C_DATA_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP,PAD_OUT_ENABLE, PAD_OUT_HIGH);Pinmux_Config(I2C_CLK_PIN, I2C0_CLK);Pinmux_Config(I2C_DATA_PIN, I2C0_DAT);// GPIO_WRITE_BIT(LED_EN_PIN, PAD_OUT_HIGH);GPIO_WRITE_BIT(LED_INTN_PIN, PAD_OUT_LOW);
}
3)配置I2C结构体
/*** @brief :配置初始化* @param :NULL* @retval :NULL*/
static void driver_init(void)
{RCC_PeriphClockCmd(APBPeriph_I2C0, APBPeriph_I2C0_CLOCK, ENABLE);I2C_InitTypeDef I2C_InitStruct;I2C_StructInit(&I2C_InitStruct);I2C_InitStruct.I2C_ClockSpeed = 200000; //< aw20108最大支持400k速率I2C_InitStruct.I2C_DeviveMode = I2C_DeviveMode_Master;I2C_InitStruct.I2C_AddressMode = I2C_AddressMode_7BIT;I2C_InitStruct.I2C_SlaveAddress = LED_DRIVER_I2C_ADDR;I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
// I2C_InitStruct.I2C_RxThresholdLevel = 12;I2C_Init(I2C0, &I2C_InitStruct);I2C_Cmd(I2C0, ENABLE);
}
4)初始化及控制
driver_led.c
#include "driver_led_driver.h"static void aw20108_soft_reset(void); //< 驱动配置初始化
static void aw20108_write_data(uint8_t reg, uint8_t data); //< 写数据
static uint8_t aw20108_read_data (uint8_t reg); //< 读数据
static void set_page(page_number_t page); //< 设置页
static void all_led_light(uint8_t level); //< 设置电流/*** @brief led驱动初始化* @param NULL* @return void*/
void aw20108_init(void)
{GPIO_WRITE_BIT(LED_EN_PIN, PAD_OUT_HIGH);DELAY_US(400);aw20108_soft_reset();
// aw20108_read_id();
}/*** @brief led驱动软件复位* @param NULL* @return void*/
static void aw20108_soft_reset(void)
{set_page(PAGE_0);aw20108_write_data(REG_SIZE, 0x08); //< 选择9x12 LEDsaw20108_write_data(REG_SLPCR, 0x00); //< 选择active modeaw20108_write_data(REG_FCD, 0x01); //< 快速清屏aw20108_write_data(REG_GCCR, 0x18); //< 最大电流20mA、强制LED为ONall_led_light(0);
}/*** @brief 读设备ID* @param NULL* @return 设备ID*/
uint8_t aw20108_read_id(void)
{uint8_t device_id = 0;set_page(PAGE_0);device_id = aw20108_read_data(REG_IDR);DBG_DIRECT("[driver_led_driver] device id: 0x%x", device_id);return device_id;
}/*** @brief 设置LED电流* @param level:led电流(亮度)* @return void*/
static void all_led_light(uint8_t level)
{uint8_t i = 0;if (level > MAX_CURR_LEVEL){level = MAX_CURR_LEVEL;}set_page(PAGE_1);for(i = 0; i <= 0x6b; i++) //< 所有灯对应的寄存器范围:0x00 ~ 0x6b{aw20108_write_data(i, 0x3f);}set_page(PAGE_2);for(i = 0; i <= 0x6b; i++) //< 所有灯对应的寄存器范围:0x00 ~ 0x6b{aw20108_write_data(i, level);}
}/*** @brief 换页* @param page:页码* @return void*/
static void set_page(page_number_t page)
{tx_data[0] = REG_PAGE;tx_data[1] = page;i2c_write(LED_DRIVER_I2C, tx_data, 2);
}/*** @brief 写数据* @param reg:寄存器、data:写入的数据* @return void*/
static void aw20108_write_data(uint8_t reg, uint8_t data)
{tx_data[0] = reg;tx_data[1] = data;i2c_write(LED_DRIVER_I2C, tx_data, 2);
}/*** @brief 读数据* @param reg:需读取的寄存器* @return 寄存器值*/
static uint8_t aw20108_read_data(uint8_t reg)
{uint8_t read_data = 0;tx_data[0] = reg;i2c_read(LED_DRIVER_I2C, tx_data, 1, &read_data, 1);return read_data;
}
driver_lcd.h
#ifndef __DRIVER_LED_DRIVER_H_
#define __DRIVER_LED_DRIVER_H_#include "hw_config.h"
#include "hw_led_aw20108.h"
#include "hw_i2c.h"#define LED_DRIVER_I2C_ADDR 0x3A
#define WRITE_BIT 0
#define READ_BIT 1#define LED_CURR_LEVEL 0x04
#define MAX_CURR_LEVEL 0x3F
#define MAX_LED_NUM 99typedef enum{PAGE_0 = 0xC0, //< 页0PAGE_1,PAGE_2,PAGE_3,PAGE_4,
}page_number_t; //< 页typedef enum{REG_IDR = 0x00,REG_SLPCR = 0x01,REG_GCCR = 0x03,REG_FCD = 0x04,REG_LEDON0 = 0x31,REG_SIZE = 0x80,REG_PAGE = 0xF0,
}reg_addr_t; //< 寄存器地址void aw20108_init(void);
uint8_t aw20108_read_id(void);#endif
4、总结
1)EN需要拉高,INTN需要拉低。
2)根据自身硬件选择不同的控制方式。
3)使用示波器或者逻辑分析仪抓波形,分析波形。
小白学习rtl8762过程中,如有不对之处,欢迎讨论,共同学习。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
