iot-fan

联系: iotfan123#163.com
注意:
1,本博客之内容来源于网上收集以及相关技术人员提供,如果有侵犯到您的权益,请电邮我沟通;
2,本博客之内容乃分享,交流,学习,研究之目的,作者不对内容的真实性,有效性,及时性负责,也不对因本博客的任何内容导致的任何后果负责;
3,本博客之内容禁止转发到CSDN网站,转到别的网站请保留出处.

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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:
image

    //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的动作 加中断屏蔽

注意事项

  1. CH578M/CH579M的 PB16 PB17 对应的是ARM-SWD调试口,如果启用了,会导致该两个io在程序中不能被控制
  2. 对于下降沿或者低电平唤醒,在进入休眠时候必须保证 对应的IO是高电平,否则电流会比较大,mA级; 对于上升沿或者高电平唤醒,在进入休眠时候必须保证 对应的IO是低电平,否则电流会比较大,mA级
  3. GPIO的原子操作问题:
  • CH57x,CH58x 系列的BLE芯片,其GPIO都是只提供了reset寄存器,并没有提供专用的set寄存器.
posted on 2021-01-20 20:45  iot-fan  阅读(3848)  评论(0编辑  收藏  举报