CH32库函数学习——CH32GPIO点亮LED(4)


前言

感谢沁恒的开发板用于学习,通过学习CH32来掌握标准库函数,虽然stm32现在都在主推HAL库,国产32还是在使用标注库,通过学习ch32来巩固标注库的相关内容。ch32与stm32高度相似,GPIO内部结构一样,对于内部原理不在一一概述,重点对标准库函数进行记录。


一、CH32F207?

CH32F205/7系列是基于Cortex-M3内核设计的工业级互联型微控制器,此系列主频高达144MHz,独立了GPIO电压(与系统供电分离)。资源同比增加了随机数单元,4组运放比较器;提高串口UART数量到8组,电机定时器到4组。搭配时钟安全、电源管理、双组DMA、DAC、SDIO、CAN、FSMC等资源。提供USB2.0高速接口(480Mbps)并内置了PHY收发器,以太网MAC升级到千兆并集成了10M-PHY模块。(其中ADC为16位,之前使用过的stm32f446只有12位,不知道stm32有没有16位ADC的单片机)

二、GPIO?

GPIO(general porpose intput output):通用输入输出端口的简称。可以通过软件控制其输出和输入。stm32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通信,控制以及数据采集的功能。
CH32F207引脚图

三、初始化函数

1.GPIO_INIT()

GPIO_Init( GPIO_TypeDef GPIOx, GPIO_InitTypeDefGPIO_InitStruct )

void GPIO_Init( GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_InitStruct )
{
    uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
    uint32_t tmpreg = 0x00, pinmask = 0x00;

    currentmode = ( ( uint32_t )GPIO_InitStruct->GPIO_Mode ) & ( ( uint32_t )0x0F );

    if( ( ( ( uint32_t )GPIO_InitStruct->GPIO_Mode ) & ( ( uint32_t )0x10 ) ) != 0x00 )
    {
        currentmode |= ( uint32_t )GPIO_InitStruct->GPIO_Speed;
    }

#if defined (CH32F20x_D6)	
		if(((*(uint32_t *) 0x40022030) & 0x0F000000) == 0)
		{
				MCU_Version = 1;
		}
		
		if((GPIOx == GPIOC) && MCU_Version){
				GPIO_InitStruct->GPIO_Pin = GPIO_InitStruct->GPIO_Pin >> 13;
		}
	
#endif
		
    if( ( ( uint32_t )GPIO_InitStruct->GPIO_Pin & ( ( uint32_t )0x00FF ) ) != 0x00 )
    {
        tmpreg = GPIOx->CFGLR;

        for( pinpos = 0x00; pinpos < 0x08; pinpos++ ){
            pos = ( ( uint32_t )0x01 ) << pinpos;
            currentpin = ( GPIO_InitStruct->GPIO_Pin ) & pos;

            if( currentpin == pos )
            {
                pos = pinpos << 2;
                pinmask = ( ( uint32_t )0x0F ) << pos;
                tmpreg &= ~pinmask;
                tmpreg |= ( currentmode << pos );

                if( GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD )
                {
                    GPIOx->BCR = ( ( ( uint32_t )0x01 ) << pinpos );
                }
                else
                {
                    if( GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU )
                    {
                        GPIOx->BSHR = ( ( ( uint32_t )0x01 ) << pinpos );
                    }
                }
            }
        }
        GPIOx->CFGLR = tmpreg;
    }

    if( GPIO_InitStruct->GPIO_Pin > 0x00FF )
    {
        tmpreg = GPIOx->CFGHR;

        for( pinpos = 0x00; pinpos < 0x08; pinpos++ ){
            pos = ( ( ( uint32_t )0x01 ) << ( pinpos + 0x08 ) );
            currentpin = ( ( GPIO_InitStruct->GPIO_Pin ) & pos );

            if( currentpin == pos )
            {
                pos = pinpos << 2;
                pinmask = ( ( uint32_t )0x0F ) << pos;
                tmpreg &= ~pinmask;
                tmpreg |= ( currentmode << pos );

                if( GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD )
                {
                    GPIOx->BCR = ( ( ( uint32_t )0x01 ) << ( pinpos + 0x08 ) );
                }

                if( GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU )
                {
                    GPIOx->BSHR = ( ( ( uint32_t )0x01 ) << ( pinpos + 0x08 ) );
                }
            }
        }
        GPIOx->CFGHR = tmpreg;
    }
}

GPIO_Init()函数为GPIO的初始化函数,函数里有两个参数,GPIOx(显而易见x为任一项)用于指定那一组IO口,第二个参数为初始化参数结构体指针,结构体类型为 GPIO_InitTypeDef,用结构体来定义GPIO的相关参数。
结构体相关成员:

typedef struct
{
 uint16_t GPIO_Pin;             /* 指明GPIO的引脚
                                   This parameter can be any value of @ref GPIO_pins_define */

 GPIOSpeed_TypeDef GPIO_Speed;  /* GPIO的引脚速度.
                                   This parameter can be a value of @ref GPIOSpeed_TypeDef */

 GPIOMode_TypeDef GPIO_Mode;    /* 指明GPIO的引脚模式.
                                   This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;

GPIO_Speed:GPIO_Speed_10MHz, GPIO_Speed_2MHz, GPIO_Speed_50MHz
GPIO_Mode:

GPIO_Mode_AIN = 0x0, //模拟输入
GPIO_Mode_IN_FLOATING = 0x04, //浮空输入
GPIO_Mode_IPD = 0x28, //下拉输入
GPIO_Mode_IPU = 0x48, //上拉输入
GPIO_Mode_Out_OD = 0x14, //开漏输出
GPIO_Mode_Out_PP = 0x10, //通用推挽输出
GPIO_Mode_AF_OD = 0x1C, //复用开漏输出
GPIO_Mode_AF_PP = 0x18 //复用推挽码片`
  • 其中在输入模式时,输出被禁止。可通过输入数据寄存器GPIOx_IDR 读取 I/O 状态。
  • 输入模式可以配置为模拟、上拉、下拉以及浮空模式。
  • 上拉和下拉输入很好理解,默认的电平由上拉或者下拉决定。
  • 浮空输入的电平是不确定的,完全由外部的输入决定。
  • 模拟输入则用于 ADC 采集。

2.最基本配置GPIO点亮LED

  1. 定义结构体名称 GPIO_InitTypeDef GPIO_InitStructure;
  2. 使能GPIO的时钟,使用每一种外设都要使能其时钟RCC_APB2PeriphClockCmd(对于是APB2还是APB1总线在系统时钟篇介绍)
  3. 调用GPIO_Init()函数初始化GPIO
  4. 设置GPIO初始电平

代码如下(示例):

void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE,ENABLE); //使能 PB,PE 端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 推挽输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 推挽输出
    GPIO_Init(GPIOE, &GPIO_InitStructure);
    GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
}

四、重要函数

void GPIO_DeInit(GPIO_TypeDef* GPIOx);//释放初始化
void GPIO_AFIODeInit(void);
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);//初始化函数
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//读取输入模式管脚的电平
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);//读取输入模式GPIO一组的电平
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//读取输出模式管脚的电平
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);//读取输出模式GPIO一组的电平
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//设置管脚的电平为高电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//设置管脚的电平为低电平
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);//写管脚的高低电平
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);//写GPIO一组的电平
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);//
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);

五、主函数

//PE5间断点亮LED
int main( void )
{
    u8 i = 0;

    NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 );
    Delay_Init();
    USART_Printf_Init( 115200 );
	LED_Init();
//    printf( "SystemClk:%d\r\n", SystemCoreClock );

//    printf( "GPIO Toggle TEST\r\n" );
//    GPIO_Toggle_INIT();

    while( 1 )
    {
        Delay_Ms(250);
		LED1=!LED1;
    }
}

PE5跳线短接LED
在这里插入图片描述

工程源码

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
HC-SR04超声波测距模块是一种常用的测距传感器,可以通过发送超声波脉冲并接收回波信号来测量距离。在STM32库函数版中,可以通过以下步骤来使用HC-SR04超声波测距模块: 1. 首先,需要包含"sys.h"头文件,并初始化HC_SR04超声波模块,可以使用HC_SR04_Init()函数进行初始化。\[1\] 2. 在测距之前,需要向Trig控制端输入至少10us的高电平触发信号,可以使用HC_SR04_start()函数发送20us的脉冲触发信号。\[1\] 3. HC-SR04模块内部会发送8个40KHz的方波并检测回波信号,一旦检测到回波信号,Echo接收端会输出高电平回响信号,高电平的持续时间就是超声波从发射到返回的时间。根据公式:距离=高电平时间*声速(340M/S)/2,可以计算出测得的距离。\[2\] 总结来说,使用STM32库函数版的HC-SR04超声波测距模块,需要初始化模块并发送触发信号,然后根据回响信号的高电平时间计算出距离。 #### 引用[.reference_title] - *1* *2* [STM32——库函数版——超声波测距模块](https://blog.csdn.net/qq_45844792/article/details/111215858)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [STM32连接HC-SR04超声波测距(结合STM32CubeMX和HAL库函数)](https://blog.csdn.net/wuwenbin12/article/details/118575989)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咕咕鸟bird

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值