热门文章
大家好,我是张飞实战电子黄忠老师,今日分享GPIO结合寄存器以及硬件电路,再来举例子分析输入输出。
寄存器介绍:
通过寄存器的位标注rw,我们可知这个寄存器的某个位是可读(r)并且可写的(w),我们也可以通过读寄存器里面的值得到引脚的配置信息,如果寄存器的位标注只有r或者w,那么就代表这个寄存器的这个位只能进行读(r)或者写(w)。
复位后IO口寄存器的值每一位可能不都是一样的,也就是说复位后IO口的状态、工作模式等不完全相同,一定要注意。
模式配置寄存器GPIOx_MODER,右上角用蓝色圆圈标识的地方告诉我们IO口的复位值,可以看到复位后对于A组IO口来说初始值0XA8000000,对于B组IO口初始值为0x00000280,其他组IO口都是0。该寄存器共 32 位,每 2个位控制 1个IO。
如图中左下角划蓝线的为第0位和第1位。通过往第0位写0,第1位写0配置成Input Mode(输入模式),通过往第0位写0,第1位写1配置成General purpose output Mode(普通输出模式),通过往第0位写1,第1位写0配置成Alternate function Mode(复用功能模式),通过往第0位写1,第1位写1配置成Analog Mode(模拟模式)。
例如我们要把这个寄存器第0位写1,其他都写0,表示如下:
GPIOA->MODER |= 0x00000001;
这就相当于把A组的PA0口配置成了普通输出模式,其他IO口配置成了输入模式。
GPIOx_OTYPER寄存器用于控制 IO 的输出类型,仅用于输出模式,在输入模式下不起作用。该寄存器低 16 位(第0位-第15位)有效,每一个位控制一个 IO 口,根据往不同的位写1(开漏输出)/写0(推挽输出)来配置成不同的输出模式。复位后,该寄存器值均为 0,即默认为推挽输出。
例如我们往A组IO口的第0位写1那就将PA0成开漏输出模式:
GPIOA->OTYPER |= 0x00000001;
GPIOx_OSPEEDR寄存器用于控制 IO的输出速度,仅用于输出模式,在输入模式下不起作用。该寄存器每 2 个位控制一个 IO 口,根据往不同的位写1/清0不同的位来配置成不同的模式。复位后对于A口来说初始值为0X0C000000,对于B口初始值0x000000C0,其他口都是0。
例如我们往A组IO口的第0位和第1位写1那就将PA0成高速输出模式:
GPIOA->OSPEEDR |= 0x00000003;
GPIOx_PUPDR寄存器用于控制 IO 的上拉/下拉,该寄存器每 2 个位控制一个 IO 口, 用于设置上下拉,根据往不同的位写1/清0不同的位来配置成不同的模式。复位后对于A口来说初始值为0X64000000,对于B口初始值0x00000100,其他口都0x0C000000。
例如我们往A组IO口的第0位写1那就将PA0下拉模式:
GPIOA->PUPDR |= 0x00000001;
GPIOx_ODR寄存器是IO口的输出数据寄存器,寄存器低 16 位(第0位-第15位)有效,寄存器每 1 个位控制一个 IO 口, 也就是这个里面位的状态代表了单片机输出的状态,根据往不同的位写1/清0不同的位来配置成不同的模式。复位后都是0。
例如我们往A组IO口的第0位写1那PA0就输出高:
GPIOA->0DR |= 0x00000001;
对于一些其他的寄存器大家可以去参考数据手册,按照上面讲述的方法去配置。
硬件设计:
图示LED灯部分我们用到了B组的2PIN(脚的简称)和4PIN, C组的15PIN, D组的8PIN, E组的8PIN和9PIN。
LED灯硬件的设计决定了LED灯的驱动方法,LED灯相当于一个发光二极管,如果单片机引脚输出高,则二极管的左边和右边电压相同,不亮,反之单片机输出低,右边电压大于左边电压通过单片机内部电路形成回路点亮二极管,那麽通过控制引脚输出的高低就控制了LED灯的亮灭。
软件设计:
下面就通过实际的寄存器来配置IO口模块,下面为LED寄存器配置代码:
void Init_GPIO(void)
{
//开启IO时钟
/**********************LED*****************************/
RCC->AHBENR |= (1<<18); //I/O port C clock enabled
RCC->AHBENR |= (1<<19); //I/O port D clock enabled
RCC->AHBENR |= (1<<20); //I/O port B clock enabled
RCC->AHBENR |= (1<<17); //I/O port A clock enabled
RCC->AHBENR |= (1<<21); //I/O port E clock enabled
GPIOB->MODER = 0; //Reset register
GPIOB->OSPEEDR = 0;//Reset register
GPIOB->PUPDR = 0;//Reset register
//GPIOB_Pin2 GPIOB_Pin4
GPIOB->MODER |= 0x00000110; //设置GPIOB_Pin2/Pin4输出模式
GPIOB->OSPEEDR |= 0x00000330;//设置GPIOB_Pin2/Pin4输出速度
GPIOB->ODR |= 0x0014; //设置GPIOB_Pin2/Pin4输出高电平
//GPIOE_Pin8 GPIOE_Pin9
GPIOE->MODER |= 0x00050000; //设置GPIOE_Pin8/Pin9输出模式
GPIOE->OSPEEDR |= 0x000F0000; //设置GPIOE_Pin8/Pin9输出速度
GPIOE->ODR |= 0x0300; //设置GPIOE_Pin8/Pin9输出高电平
//GPIOD_Pin8
GPIOD->MODER |= 0x00010000; //设置GPIOD_Pin8输出模式
GPIOD->OSPEEDR |= 0x00030000; //设置GPIOD_Pin8输出速度
GPIOD->ODR |= 0x0100; //设置GPIOD_Pin8输出高电平
//GPIOC_Pin15
GPIOC->MODER |= 0x40000000; //设置GPIOC_Pin15输出模式
GPIOC->OSPEEDR |= 0xC0000000; //设置GPIOC_Pin15输出速度
GPIOC->ODR |= 0x8000; //设置GPIOC_Pin15输出高电平
}
上面没有配置的寄存器我们使用默认值,通过改变输出数据寄存器(ODR)的值,控制某一个引脚输出高和低控制LED灯的状态。
例如:控制IO输出高电平:
GPIOD->ODR |= 0x0100; //设置GPIOD_Pin8输出高电平
控制IO输出低电平:
GPIOD->ODR &= 0xFEFF; //设置GPIOD_Pin8输出低电平
在这里我们仅配置IO口的推挽高速输出,不上拉,不下拉模式作为演示,大家也可以根据上面介绍的方法去配置调试其他模式,GPIO部分设计实现介绍就在此结束,若有不理解的欢迎交流~
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表乌云踏雪网立场。
文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。