在查看控制器板卡原理图后可以发现板卡板载了三个RGB LED灯。一个是通过芯片I/O直接控制的RGB LED灯;另外一个是通过电源管理芯片MAX20303BEWN+间接控制的;最后一个是连接在另外一个32位微控制器MAX32625IWY的引脚上。前两个RGB LED灯对应的原理图分别如下
其中第一个是MAX78000直接控制的RGB LED灯,红色LED灯对应的引脚号是P2_0;绿色LED灯对应的引脚号是P2_1;蓝色LED灯对应的引脚号是P2_2。第二个是MAX20303BEWN+芯片控制的RGB LED灯,可以通过IIC间接控制。
第一个RGB LED灯的控制可以直接通过Hello_World例程的源码进行控制,创建好Hello_World的例程后,main函数的源码如下:
int count = 0; printf("Hello World!\n"); while (1) { LED_On(LED1); MXC_Delay(500000); LED_Off(LED1); MXC_Delay(500000); printf("count : %d\n", count++); }
可以看出对应的RGB LED灯对应的GPIO引脚直接被定义成LED1了。查看LED1的定义如下
可以看出LED1对应的是红色LED灯;LED2对应的是绿色的LED灯;LED3对应的是蓝色的LED灯。其各自的宏定义的数字对应各自的I/O引脚号。RGB LED灯的亮灭是通过函数LED_On和LED_Off控制的,并且也进行了封装。源码只有对LED1的亮灭控制,所以为了点亮所有的RGB LED灯,所以修改源码为
int count = 0; printf("Hello World!\n"); while (1) { LED_On(LED1); MXC_Delay(500000); LED_Off(LED1); LED_On(LED2); MXC_Delay(500000); LED_Off(LED2); LED_On(LED3); MXC_Delay(500000); LED_Off(LED3); printf("count : %d\n", count++); }
其作用是先让红绿蓝灯各自亮一定的时间。效果如下
回过头来看main函数时发现没有时钟初始化和GPIO引脚初始化等就可以直接控制RGB LED灯了。看工程没有包含其他的.c文件,所以肯定在main函数被调用之前调用了某个函数来初始化它们。再看工程的.o文件有led.o和board.o两个文件,led.o就不用多说了,是控制LED灯的;而board.o文件一般是用作板载资源的初始化的,所以可能存在board.c,并且初始化了相关的资源。再看工程包含的Includes文件夹有对应的.h工程文件路径,所以可以通过这个路径找到对应的.c文件,而路径是软件安装路径的子文件夹下。通过在软件安装路径下所搜board可以找到对应的.c文件,一定要注意板卡的类型为FTHR_RevA,所以要看这个文件夹下的board.c文件。打开后可以在Board_Init函数看到LED的初始化源码
if ((err = LED_Init()) != E_NO_ERROR) { MXC_ASSERT_FAIL(); return err; }
而LED_Init函数的源码在led.c文件中,可以通过同样的方式搜索到led.c的文件,对应的源码如下
int LED_Init(void) { int retval = E_NO_ERROR; unsigned int i; /* setup GPIO for the LED */ for (i = 0; i < num_leds; i++) { LED_Off(i); // Set the output value if (MXC_GPIO_Config(&led_pin[i]) != E_NO_ERROR) { retval = E_UNKNOWN; } } return retval; }
其中先是关闭所有的LED灯,然后对其引脚进行初始化,初始化的配置参数在led_pin数组中,而led_pin数组的定义和赋初值在board.c中,对应的源码如下
const mxc_gpio_cfg_t led_pin[] = { { MXC_GPIO2, MXC_GPIO_PIN_0, MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH, MXC_GPIO_DRVSTR_0}, { MXC_GPIO2, MXC_GPIO_PIN_1, MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH, MXC_GPIO_DRVSTR_0}, { MXC_GPIO2, MXC_GPIO_PIN_2, MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH, MXC_GPIO_DRVSTR_0}, };
通过前两个数组元素的初值,可以看到对应LED灯的完整引脚号P2_x(0,1,2)。
然后是控制接在芯片MAX20303的RGB LED灯了。简单的方式是创建一个FTHR_I2C的例程。
创建后的源码如下
MXC_Delay(MXC_DELAY_MSEC(500)); //Wait for PMIC to power-up printf("\n******** Featherboard I2C Demo *********\n"); printf("\nThis demo uses I2C to change the state of the\n"); printf("on-board Power Management IC's RGB LED every second.\n"); printf("\nYou should observe the LED cycling through it's\n"); printf("eight color states.\n"); int error, i = 0; //Setup the I2CM error = MXC_I2C_Init(PMIC_I2C, 1, 0); if (error != E_NO_ERROR) { printf("-->Failed master\n"); while (1) {} } else { printf("\n-->I2C Initialization Complete"); } MXC_I2C_SetFrequency(PMIC_I2C, I2C_FREQ); // Set the LED current strength mxc_i2c_req_t reqMaster; reqMaster.i2c = PMIC_I2C; reqMaster.addr = PMIC_SLAVE_ADDR; reqMaster.tx_buf = tx_buf; reqMaster.tx_len = INIT_LEN; reqMaster.rx_buf = NULL; reqMaster.rx_len = 0; reqMaster.restart = 0; tx_buf[0] = LED_CFG_REG_ADDR; tx_buf[1] = 1; //Set LED current to 1mA if ((error = MXC_I2C_MasterTransaction(&reqMaster)) != 0) { printf("Error writing: %d\n", error); while (1) {} } while (1) { MXC_Delay(MXC_DELAY_SEC(1)); SetLEDs(i); i = (i + 1) % 8; //Cycle through 8 LED Colors }
其中可以在while循环中看到设置LED亮灭函数为SetLEDs,而SetLEDs函数源码如下
void SetLEDs(int state) { int error; // Set the LED Color mxc_i2c_req_t reqMaster; reqMaster.i2c = PMIC_I2C; reqMaster.addr = PMIC_SLAVE_ADDR; reqMaster.tx_buf = tx_buf; reqMaster.tx_len = LED_SET_LEN; reqMaster.rx_buf = NULL; reqMaster.rx_len = 0; reqMaster.restart = 0; tx_buf[0] = LED_SET_REG_ADDR; tx_buf[1] = (uint8_t)((state & PMIC_LED_BLUE) << 5); //Set Blue LED? tx_buf[2] = (uint8_t)((state & PMIC_LED_RED) << 4); //Set Red LED? tx_buf[3] = (uint8_t)((state & PMIC_LED_GREEN) << 3); //Set Green LED? if ((error = MXC_I2C_MasterTransaction(&reqMaster)) != 0) { printf("Error writing: %d\n", error); while (1) {} } }
可以看到是通过某个字节的某一位来控制RGB LED灯的亮灭的。下载后的效果如下