从今天开始进入例程的解释过程,今天的解释GPIO部分,对应《AN220-CMT2380F32用户指南(微控制器部分)-CN-V1.0-20200107.pdf》7 端口控制器(GPIO)章节。
例程位置在\example\gpio在文件夹中,有四个例程,下面逐一解释。
gpio_output例程
这个例程是输出例程,按键1按下后,led灯闪烁。以下是主要代码。
#define SK_SW1_INIT() Gpio_InitIOExt(0, 2, GpioDirIn, TRUE, FALSE, FALSE, TRUE) #define SK_SW1_GET() Gpio_GetIO(0, 2)
这两个宏定义是按键1的函数,INIT是将按键1,P02配置为输入,上拉模式。GET是获取P02的IO值。根据我的开发板电路,按下按钮时IO口被拉低,get值为0,当未按下时,由于配置为上拉电阻,因此get值为非0。
const stc_gpio_list_t gGpiolist[] = { {2, 3}, // red {1, 4}, // green {1, 5}, // blue };
这个是LED的IO管脚配置,因为我们有三个开发板LED,所以这里有三个数组。
SK_SW1_INIT(); delay1ms(10); while (TRUE == SK_SW1_GET()) ; //外部初始化GPIO for (i = 0; i < ARRAY_SZ(gGpiolist); i ) { Gpio_InitIOExt(gGpiolist[i].u8Port, gGpiolist[i].u8Pin, GpioDirOut, TRUE, FALSE, FALSE, FALSE); } //设置GPIO值(翻转) while (1) { for (i = 0; i < ARRAY_SZ(gGpiolist); i ) { Gpio_SetIO(gGpiolist[i].u8Port, gGpiolist[i].u8Pin, u8val); } u8val = !u8val; delay1ms(1000); }
以上是main函数中的主要代码首先初始化P02,然后通过get按下按钮等待按钮。
按键后初始化LED上拉输出。然后进入while循环使用Gpio_SetIO进行IO 翻转。
gpio_input例程
//检测K1.如果输入为低电平,则Led1_red输出3秒 while (1) { for (i = 0; i < ARRAY_SZ(gGpiolist); i ) { u8val = Gpio_GetIO(gGpiolist[i].u8Port, gGpiolist[i].u8Pin); if (FALSE == u8val) { Gpio_SetIO(gLed1list[0].u8Port, gLed1list[0].u8Pin, TRUE); delay1ms(3000); Gpio_SetIO(gLed1list[0].u8Port, gLed1list[0].u8Pin, FALSE); } } }
初始化过程与以前相似,但在while按钮检测在循环中进行,按下按钮LED1点亮3秒。
gpio_irq例程
例程显示IO中断功能。上电时led2,led3电量,按键1后led将熄灭3秒,然后点亮。
//中断触发功能 for (i = 0; i < ARRAY_SZ(gIrqList); i ) { Gpio_EnableIrq(gIrqList[i].u8Port, gIrqList[i].u8Pin, GpioIrqFalling); } //开启GPIO总中断 EnableNvic(PORT0_IRQn, DDL_IRQ_LEVEL_DEFAULT, TRUE); while (1) ;
主函数中将P02配置为下降沿触发,GpioIrqFalling。EnableNvic使能中断。
void Gpio_IRQHandler(uint8_t u8Param) { SK_LED_SET(1); delay1ms(3000); SK_LED_SET(0); delay1ms(2000); *((uint32_t *)((uint32_t)&M0P_GPIO->P0ICLR u8Param * 0x40)) = 0; }
将中断函数led关闭3秒后打开,整个中断占用5秒,整个中断只是一个例子,在真实代码中尽量减少中断时间。
gpio_lpm例程
例程功能通过配置IO 中断,唤醒睡眠模块。上电后,按下按钮1,LED2,LED3点亮,然后LED2.熄灭2秒,然后在2秒后进入睡眠,然后按下按钮1,LED2会熄灭2秒,然后亮起。让我们看看逻辑。
//将中断触发功能 for (i = 0; i < ARRAY_SZ(gIrqList); i ) { Gpio_EnableIrq(gIrqList[i].u8Port, gIrqList[i].u8Pin, GpioIrqFalling); } EnableNvic(PORT0_IRQn, DDL_IRQ_LEVEL_DEFAULT, TRUE); M0P_GPIO->CTRL0_f.IESEL = 1; Clk_SetFunc(ClkFuncWkupRCH, TRUE); SCB->SCR |= 0x4; // sleepdeep __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); while (1) { SK_LED_SET(1); delay1ms(2000); SK_LED_SET(0); delay1ms(2000); __WFI(); // goto LPM Mode }
中断,然后点亮LED2,LED3。然后在while中先熄灭LED22秒后点亮,2秒后睡觉,等待IO中断唤醒,继续while逻辑。
中断标志位只在中断处理中被清除。
void Gpio_IRQHandler(uint8_t u8Param) { *((uint32_t *)((uint32_t)&M0P_GPIO->P0ICLR u8Param * 0x40)) = 0; }
必须初始化等待按钮1按下此函数的逻辑,因为模块进入睡眠后无法链接调试器下载。
// SW1 控制程序继续运行 //注:如果程序在这里继续运行,由于演示的需要,它将继续运行SWD及RESET配置为IO使用此功能Demo请勿删除以下两行代码。 SK_SW1_INIT(); NextStep();
GPIO正是这些,也是一个相对简单的例程,没有太多的东西,提供的图书馆有非常详细的中文注释,参数可以很容易地理解使用,非常友好的开发。