文章目录
前言
前段时间有在使用华润微CS32ME10的芯片,但是个人用不太习惯官方的库以及例程,所以闲暇之时就将大部分库函数重构了一遍(如下图所示部分外设 ),并且将一些经常用到的功能例程重新梳理一遍,方便以后使用测试。当然我现在写的这个教程步骤也是同样契合官方例程的,如果在使用官方库时出现疑问,也可以先按照此教程的步骤先排查寄存器设置是否正确。

一、华润微电子简介;
华润微电子有限公司是华润集团旗下负责微电子业务投资、发展和经营管理的高科技企业。目前微电子下设四大事业群分别是集成电路事业群(ICBG)、功率器件事业群(PDBG)、代工事业群(FBG)、封测事业群(ATBG),其中ICBG全面负责功率IC、智能传感器、智能控制、系统应用及方案设计与开发的业务单元。感兴趣的可以去官网看看:华润微电子官网链接
二、CS32ME10-GPIO模块简介;
CS32ME10 包含 6 组输入/输出端口,每个端口可以配置内部输入上拉、输入下拉、开漏输出、输入高阻、CMOS 推挽输出,芯片复位后,端口为高阻输入状态(通过实验验证,确实不能做普通上拉输出和普通下拉输出,但是开漏输出时内部上下拉起作用)如下所示:

三、GPIO模块使用;
3.1.GPIO之推挽输出;
推挽输出(Push-Pull Output) 是数字电路中一种常见的输出模式,主要特点是既能主动输出高电平,也能主动输出低电平,驱动能力强。其内部由两个晶体管(一个PMOS,一个NMOS)组成。
当输出高电平时:上管(PMOS)导通,下管(NMOS)截止,输出直接连接到VCC;
当输出低电平时:上管截止,下管导通,输出直接连接到GND。
CS32ME10推挽输出配置步骤:
1、打开相应端口时钟;
2、配置OE寄存器,使能相应引脚的输出功能;
3、写DIO寄存器即可控制io口变换。
c
void gpio_out_test(void)
{
/* 打开外设时钟*/
Rcc_Periph_config(RCC_Periph_GPIOB, ENABLE);
/* 使能IO推挽输出功能*/
Gpio_out_config(GPIOB_MODULE, GPIO_PIN_6, ENABLE);
while(1)
{
Gpio_bit_set(GPIOB_MODULE,GPIO_PIN_6); //引脚置高电平
delay_ms(50);
Gpio_bit_reset(GPIOB_MODULE,GPIO_PIN_6); //引脚置低电平
delay_ms(50);
}
}
3.2.GPIO之开漏输出;
开漏输出(Open-Drain Output) 是数字电路中另一种常见的输出模式。它的特点是:只能主动输出低电平,无法主动输出高电平(因为大部分情况都是上管的Pmos不工作,引脚直接连接到下管NMOS的漏极了);要输出高电平,必须在外部加上拉电阻。
输出低电平时:下管NMOS导通,输出引脚被直接拉到 GND(0V);
输出高电平时:下管NMOS截止,输出引脚呈现 高阻态 (Hi-Z),引脚的实际电压由外部电路决定。
CS32ME10开漏输出配置步骤:
1、打开相应端口时钟;
2、配置OE寄存器,使能相应引脚的输出功能,再配置OD寄存器,使能开漏功能;
3、一般开漏输出需要外接上拉电阻才能用。
c
void gpio_od_out_test(void)
{
/* 打开外设时钟*/
Rcc_Periph_config(RCC_Periph_GPIOB, ENABLE);
/* 使能IO推挽输出功能*/
Gpio_out_config(GPIOB_MODULE, GPIO_PIN_6, ENABLE);
Gpio_od_out_config(GPIOB_MODULE, GPIO_PIN_6, ENABLE);
while(1)
{
Gpio_bit_set(GPIOB_MODULE,GPIO_PIN_6); //引脚置高电平
delay_ms(50);
Gpio_bit_reset(GPIOB_MODULE,GPIO_PIN_6); //引脚置低电平
delay_ms(50);
}
}
3.3.GPIO之输入功能;
输入功能 一般是芯片为了读取外部信号设置的,大部分输入引脚内部都有一个 施密特触发器。它的作用是将外部可能不规则的电压(比如慢慢上升的2.5V)整形成芯片能识别的、陡峭的 0 或 1 数字信号,然后这个数字信号到达输入数据寄存器里,CPU就可以读取外部的电平状态了。
CS32ME10输入功能配置步骤:
1、打开相应端口时钟;
2、配置IE寄存器,使能io输入功能;
3、读取DIO寄存器值获取输入状态;
c
void gpio_in_test(void)
{
/* 打开外设时钟*/
Rcc_Periph_config(RCC_Periph_GPIOB, ENABLE);
/* 使能io输入功能*/
Gpio_in_config(GPIOB_MODULE, GPIO_PIN_7, ENABLE);
// Gpio_updown_in_config(GPIOB_MODULE,GPIO_PIN_0,0,1,ENABLE); //上下拉配置
/* 使能输出*/
Gpio_out_config(GPIOB_MODULE, GPIO_PIN_6, ENABLE);
while(1)
{
if(Gpio_bit_read(GPIOB_MODULE, GPIO_PIN_7))
{
Gpio_bit_set(GPIOB_MODULE,GPIO_PIN_6);
}
else
{
Gpio_bit_reset(GPIOB_MODULE,GPIO_PIN_6);
}
}
}
3.4.GPIO之IO中断功能;
GPIO外部中断 是绝大部分芯片都具备的常用功能,当GPIO引脚上的电平发生变化(如从高变低、从低变高且使能了相应中断)时,芯片内部会自动触发CPU打断当前执行的函数转而去执行中断处理函数,而不需要CPU不断轮询检查引脚状态。
CS32ME10 GPIO外部中断配置步骤:
1、打开IO端口时钟;
2、使能输入;
3、使能IO复用为中断功能;
4、配置外部中断模块触发模式及使能;
5、配置外部中断优先级;
6、使能中断;
7、具体的中断处理过程。
c
/* io外部中断测试*/
void io_int_test(void)
{
/* 打开IO端口时钟 */
Rcc_Periph_config(RCC_Periph_GPIOB, ENABLE);
/* 使能IO输入*/
Gpio_in_config(GPIOB_MODULE, GPIO_PIN_7, ENABLE);
/* 使能IO复用为中断功能*/
Gpio_af_exti_config(GPIOB_MODULE, GPIO_PIN_7, ENABLE);
/* 配置外部中断模块触发模式及使能*/
Exti_config(EXTI_SOURCE_PORTB, EXTI_INT_BOTH, ENABLE);
/* 配置外部中断优先级*/
NVIC_SetPriority(PORTB_IRQn,2);
/* 配置pb6为输出模式*/
Gpio_out_config(GPIOB_MODULE, GPIO_PIN_6, ENABLE);
/* 使能中断*/
NVIC_EnableIRQ(PORTB_IRQn);
//.....具体执行过程见中断处理函数
while(1)
{
}
}
/**
* @name :PORTB_IRQHandler
* @功能 :端口B中断服务函数
* @param :无
* @retval: 无
*/
void PORTB_IRQHandler(void)
{
if(EXTI_MODULE->EXTI_SR&0x02) //判断是否产生中断
{
EXTI_MODULE->EXTI_PICR0 |= 0xc000; //软件清除Port B 端口中断事件标志位-PB
/* 添加用户代码*/
if(Gpio_bit_read(GPIOB_MODULE,GPIO_PIN_7))
{
Gpio_bit_set(GPIOB_MODULE,GPIO_PIN_6);
}
else
{
Gpio_bit_reset(GPIOB_MODULE,GPIO_PIN_6);
}
}
}
四、GPIO模块重构版库函数;
c
#include "me10_gpio.h"
/*--------------------------------------------------------引脚通用输入输出配置函数------------------------------------------------*/
/**
* @name :Gpio_out_config
* @功能 :GPIO普通(推挽)输出配置
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param flag 输出使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_out_config(GPIO_REG* Gpio_module, uint8_t pin, FunctionalState flag)
{
if(flag)
{
Gpio_module->OE |= pin; //使能相应模块pin脚的输出功能
}
else
{
Gpio_module->OE &= ~pin; //禁止相应模块pin脚的输出功能
}
}
/**
* @name :Gpio_od_out_config
* @功能 :GPIO开漏输出配置
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param flag 开漏输出使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_od_out_config(GPIO_REG* Gpio_module, uint8_t pin, FunctionalState flag)
{
if(flag)
{
Gpio_module->OE |= pin; //使能相应模块pin脚的开漏输出功能
Gpio_module->OD |= pin;
Gpio_module->UP |= pin;
}
else
{
Gpio_module->OE &= ~pin; //禁止相应模块pin脚的开漏输出功能
Gpio_module->OD &= ~pin;
Gpio_module->UP &= ~pin;
}
}
/**
* @name :Gpio_bit_set
* @功能 :GPIO引脚置1
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @retval: 无
*/
void Gpio_bit_set(GPIO_REG* Gpio_module,uint8_t pin)
{
Gpio_module->DIO |= pin;
}
/**
* @name :Gpio_bit_reset
* @功能 :GPIO引脚置0
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @retval: 无
*/
void Gpio_bit_reset(GPIO_REG* Gpio_module,uint8_t pin)
{
Gpio_module->DIO &= (uint8_t)(~pin);
}
/**
* @name :Gpio_in_config
* @功能 :GPIO普通(浮空)输入配置
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param flag 输入使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_in_config(GPIO_REG* Gpio_module, uint8_t pin, FunctionalState flag)
{
if(flag)
{
Gpio_module->IE |= pin; //使能相应模块pin脚的输入功能
}
else
{
Gpio_module->IE &= ~pin; //禁止相应模块pin脚的输入功能
}
}
/**
* @name Gpio_updown_in_config
* @功能 :GPIO上下拉输入配置
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param up 上拉使能控制 (不能同时上下拉)
@1:使能
@0:关闭
* @param down 下拉使能控制 (不能同时上下拉)
@1:使能
@0:关闭
* @param flag 输入使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_updown_in_config(GPIO_REG* Gpio_module,uint8_t pin,uint8_t up,uint8_t down,FunctionalState flag)
{
if(up & down) //不能同时上下拉
{
return;
}
if(flag)
{
Gpio_module->IE |= pin; //使能相应模块pin脚的输入功能
if(up)
{
Gpio_module->UP |= pin; //配置相应的上拉寄存器
}
else
{
Gpio_module->UP &= ~pin; //配置相应的上拉寄存器
}
if(down)
{
Gpio_module->DN |= pin; //配置相应的下拉寄存器
}
else
{
Gpio_module->DN &= ~pin; //配置相应的下拉寄存器
}
}
else
{
Gpio_module->IE &= ~pin; //禁止相应模块pin脚的输入功能
Gpio_module->UP &= ~pin; //配置相应的上拉寄存器
Gpio_module->DN &= ~pin; //配置相应的下拉寄存器
}
}
/**
* @name :Gpio_bit_read
* @功能 :读取相应引脚的值
* @param Gpio_module 需要读取的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要读取的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @retval: 1:高电平,0:低电平
*/
uint8_t Gpio_bit_read(GPIO_REG* Gpio_module,uint8_t pin)
{
uint8_t reval;
reval = Gpio_module->DIO&pin;
return reval;
}
/*--------------------------------------------------------引脚引脚复用功能配置函数------------------------------------------------*/
/**
* @name Gpio_af_exti_config
* @功能 :GPIO引脚复用中断功能使能或关闭
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param flag 输入使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_af_exti_config(GPIO_REG* Gpio_module, uint8_t pin, FunctionalState flag)
{
if(flag)
{
Gpio_module->AF7 |= pin; //使能相应pin脚的外部中断
}
else
{
Gpio_module->AF7 &= ~pin; //失能相应pin脚的外部中断
}
}
/**
* @name Gpio_af_uart_config
* @功能 :GPIO引脚复用串口功能使能或关闭
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param flag 串口复用功能使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_af_uart_config(GPIO_REG* Gpio_module, uint8_t pin, FunctionalState flag)
{
if(flag)
{
Gpio_module->AF5 |= pin; //使能相应pin脚的串口复用功能
}
else
{
Gpio_module->AF5 &= ~pin; //失能相应pin脚的串口复用功能
}
}
/**
* @name Gpio_af_ssp_config
* @功能 :GPIO引脚复用SSP功能使能或关闭
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param flag SSP复用功能使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_af_ssp_config(GPIO_REG* Gpio_module, uint8_t pin, FunctionalState flag)
{
if(flag)
{
Gpio_module->AF4 |= pin; //使能相应pin脚的SSP复用功能
}
else
{
Gpio_module->AF4 &= ~pin; //失能相应pin脚的SSP复用功能
}
}
/**
* @name Gpio_af_iic_config
* @功能 :GPIO引脚复用IIC功能使能或关闭
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param flag IIC复用功能使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_af_iic_config(GPIO_REG* Gpio_module, uint8_t pin, FunctionalState flag)
{
if(flag)
{
Gpio_module->AF6 |= pin; //使能相应pin脚的IIC复用功能
}
else
{
Gpio_module->AF6 &= ~pin; //失能相应pin脚的IIC复用功能
}
}
/**
* @name Gpio_af_tim_pwm_config
* @功能 :GPIO引脚复用TIM PWM输出功能使能或关闭
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param flag TIM PWM复用功能使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_af_tim_pwm_config(GPIO_REG* Gpio_module, uint8_t pin, FunctionalState flag)
{
if(flag)
{
Gpio_module->AF1 |= pin; //使能相应pin脚的TIM PWM复用功能
}
else
{
Gpio_module->AF1 &= ~pin; //失能相应pin脚的TIM PWM复用功能
}
}
/**
* @name Gpio_af_tim_capture_config
* @功能 :GPIO引脚复用TIM 输入捕获功能使能或关闭
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param flag TIM 输入捕获复用功能使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_af_tim_capture_config(GPIO_REG* Gpio_module, uint8_t pin, FunctionalState flag)
{
if(flag)
{
Gpio_module->AF3 |= pin; //使能相应pin脚的TIM 输入捕获复用功能
}
else
{
Gpio_module->AF3 &= ~pin; //失能相应pin脚的TIM 输入捕获复用功能
}
}
/**
* @name Gpio_af_pmd_config
* @功能 :GPIO引脚复用PMD-UVW输出功能使能或关闭
* @param Gpio_module 需要配置的GPIO模块
@arg GPIOA_MODULE
@arg GPIOB_MODULE
@arg GPIOC_MODULE
@arg GPIOD_MODULE
@arg GPIOE_MODULE
@arg GPIOF_MODULE
* @param pin 需要配置的pin脚
@arg GPIO_PIN_0
@arg GPIO_PIN_1
@arg GPIO_PIN_2
@arg GPIO_PIN_3
@arg GPIO_PIN_4
@arg GPIO_PIN_5
@arg GPIO_PIN_6
@arg GPIO_PIN_7
* @param flag PMD-UVW复用功能使能或关闭
@ENABLE:使能
@DISABLE:关闭
* @retval: 无
*/
void Gpio_af_pmd_config(GPIO_REG* Gpio_module, uint8_t pin, FunctionalState flag)
{
if(flag)
{
Gpio_module->AF0 |= pin; //使能相应pin脚的PMD复用功能
}
else
{
Gpio_module->AF0 &= ~pin; //失能相应pin脚的PMD复用功能
}
}
*此教程仅记录个人使用过程,仅供参考学习,且本教程使用的库函数均为重构的版本,不代表官方文档,谢谢!