CH579/CH573/CH57x GPIO使用
其实不是很想写,无奈有时候还是写写,用到时候贴代码比较快
适用芯片
- CH579/CH578/CH577
- CH573/CH571
- CH581/CH582/CH583
CH57x/CH58x GPIO特点
从手册上看,WCH的CH57x,CH58x其GPIO寄存器基本是一致的,其提供的SDK的代码也基本一致
- CH577/578/579只有Px0-15支持中断
- CH571/573 全部IO都支持中断
- 所有的中断都支持中断唤醒
- 睡眠后IO的状态可以保持
- 没有专门的开漏模式支持(实现开漏可参阅此文章)
SDK里提供的函数的使用
//CH57x只有两个Port,wch的驱动是分别用不同的函数来对待的
//初始化PA9,推拉模式输出,5mA驱动能力
GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
//拉高PA9
GPIOA_SetBits(GPIO_Pin_9);
//拉高PA8,PA9
GPIOB_SetBits(GPIO_Pin_8|GPIO_Pin_9);
//拉低PB3
GPIOB_ResetBits(GPIO_Pin_3);
//反转IO
GPIOB_InverseBits(GPIO_Pin_3);
//读GPIOA port
GPIOA_ReadPort();
//读GPIOB port
GPIOB_ReadPort();
//读PAx的值
//GPIOA_ReadPortPin的返回值并不是bool值,而是对应的port&pin的值
GPIOA_ReadPortPin( pin );
外部中断
在CH577/CH578/CH579上
//初始化位输入上拉
GPIOB_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
//开启下降沿中断
GPIOB_ITModeCfg(GPIO_Pin_8,GPIO_ITMode_FallEdge);
//开启GPIO的睡眠唤醒,如果需要的话
PWR_PeriphWakeUpCfg( ENABLE, RB_SLP_GPIO_WAKE );
//开启GPIO中断
NVIC_EnableIRQ( GPIO_IRQn );
//中断服务程序
void GPIO_IRQHandler(void) {
PRINT("gpio interrupt\r\n");
GPIOB_ClearITFlagBit(GPIO_Pin_8);
}
在CH571/CH573上
void gpio_wake_init() {
//初始化位输入上拉
GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU);
//开启下降沿中断
GPIOB_ITModeCfg(GPIO_Pin_4,GPIO_ITMode_FallEdge);
//开启GPIO睡眠唤醒
PWR_PeriphWakeUpCfg( ENABLE, RB_SLP_GPIO_WAKE,Edge_LongDelay );
//开启GPIOB中断
PFIC_EnableIRQ(GPIO_B_IRQn);
}
//中断服务程序
__attribute__((interrupt("WCH-Interrupt-fast"))) //告诉编译器使用硬件压栈
__attribute__((section(".highcode"))) //放到RAM里
void GPIOB_IRQHandler(void) {
PRINT("gpio interrupt\r\n");
GPIOB_ClearITFlagBit(GPIO_Pin_4);
}
外设重映射
CH57Xx系列的芯片,很多数字外设都支持 端口重映射(只是映射到芯片支持的第二个IO上)
如在ch573/ch571上 把UART1 从默认的PA8,PA9映射到PB12:
//remap uart1 to PB13/PB12
//使能对应的外设重映射
GPIOPinRemap( ENABLE, RB_PIN_UART1 );
//初始化对应外设映射后的gpio
GPIOB_SetBits(bTXD1_);
GPIOB_ModeCfg(bTXD1_, GPIO_ModeOut_PP_5mA);
GPIOB_ModeCfg( bRXD1_, GPIO_ModeIN_PU );
//初始化对应的外设
UART1_DefInit( );
中断里面操作GPIO
ch57x,ch58x的GPIO只提供了专门的CLR寄存器, 没有专门的SET寄存器,设置高电平是通过OUT寄存器实现的,
这个操作不具备原子特性,这样在中断里面操作就相当于修改全局变量,存在风险
- 如果只是拉低GPIO,可以直接使用R32_PA_CLR=GPIO_Pin_xx 或者32_PB_CLR=GPIO_Pin_xx 实现,在中断外面操作gpio不用加额外处理
- 如果需要在中断里存在拉高GPIO的情况, 如果在中断外面也操作GPIO,那就需要外面操作GPIO的动作 加中断屏蔽
注意事项
- CH578M/CH579M的 PB16 PB17 对应的是ARM-SWD调试口,如果启用了,会导致该两个io在程序中不能被控制
- 对于下降沿或者低电平唤醒,在进入休眠时候必须保证 对应的IO是高电平,否则电流会比较大,mA级; 对于上升沿或者高电平唤醒,在进入休眠时候必须保证 对应的IO是低电平,否则电流会比较大,mA级
- GPIO的原子操作问题:
- CH57x,CH58x 系列的BLE芯片,其GPIO都是只提供了reset寄存器,并没有提供专用的set寄存器.