当前位置:网站首页>STM32学习笔记3——GPIO的输入引脚
STM32学习笔记3——GPIO的输入引脚
2022-04-22 05:40:00 【锂盐块呀】
STM32学习笔记3——GPIO的输入引脚
写在前面
果然我还要学习很多东西,记录今天怎么解决上次加按键就不能正常运作的问题。
一、代码对比
1、原先代码
根据库函数版本下意识写出来的寄存器版:
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//PC
RCC->APB2ENR |= (1<<4);
GPIOC->CRL &= 0xFFFFFF0F;//PC1
GPIOC->CRL |= 0x00000080;
GPIOC->CRH &= 0xFF0FFFFF;//PC13
GPIOC->CRH |= 0x00800000;
//PA
RCC->APB2ENR |= (1<<2);
GPIOA->CRL &= 0xFFFFFFF0;//PA0
GPIOA->CRL |= 0x00000008;
}
2、最终代码
一步步纠错修改后的程序
void Key_GPIO_Config(void)
{
//PC
RCC->APB2ENR |= (1<<4);
GPIOC->CRL &= 0xFFFFFF0F;
GPIOC->CRL |= 0x00000080;
GPIOC->BSRR |= (1<<1);//set
GPIOC->CRH &= 0xFF0FFFFF;
GPIOC->CRH |= 0x00800000;
GPIOC->BSRR |= (1<<13);//set
//PA
RCC->APB2ENR |= (1<<2);
GPIOA->CRL &= 0xFFFFFFF0;
GPIOA->CRL |= 0x00000008;
GPIOC->BRR |= (1<<0);//reset
}
二、经验总结
1、怎么定位和修改代码的?
逐行注释,逐行修改,逐渐定位到问题点。
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//PC 第一次修改的使能时钟语句,编译运行,没有任何问题
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC->APB2ENR |= (1<<4);
/* 第二次修改的是PC口的引脚配置 PC两个按键不起作用 GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1|GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; GPIO_Init(GPIOC,&GPIO_InitStructure); */
GPIOC->CRL &= 0xFFFFFF0F;
GPIOC->CRL |= 0x00000080;
GPIOC->CRH &= 0xFF0FFFFF;
GPIOC->CRH |= 0x00800000;
//PA 第一次修改的使能时钟语句,编译运行,没有任何问题
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC->APB2ENR |= (1<<2);
/* 第三次修改的是PA口的引脚配置 PA口的按键正常运行,PC口按键不起作用 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; GPIO_Init(GPIOA,&GPIO_InitStructure); */
GPIOA->CRL &= 0xFFFFFFF0;
GPIOA->CRL |= 0x00000008;
}
第一次修改的使能时钟语句,编译运行,没有任何问题。
第二次修改的是PC口的引脚配置 PC口两个按键不起作用。
第三次修改的是PA口的引脚配置 PA口的按键正常运行,PC口按键不起作用。
在检查了C口引脚没有定义错误的情况下,可以定位出我在配置输入口时有问题,转到GPIO_Init这个函数定义看我是不是少了什么。
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;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
/*---------------------------- GPIO Mode Configuration -----------------------*/
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
{
/* Check the parameters */
assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
/* Output mode */
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
}
/*---------------------------- GPIO CRL Configuration ------------------------*/
/* Configure the eight low port pins */
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
{
tmpreg = GPIOx->CRL;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = ((uint32_t)0x01) << pinpos;
/* Get the port pins position */
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
if (currentpin == pos)
{
pos = pinpos << 2;
/* Clear the corresponding low control register bits */
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos);
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
}
else
{
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
}
}
}
}
GPIOx->CRL = tmpreg;
}
/*---------------------------- GPIO CRH Configuration ------------------------*/
/* Configure the eight high port pins */
if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
{
tmpreg = GPIOx->CRH;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = (((uint32_t)0x01) << (pinpos + 0x08));
/* Get the port pins position */
currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
if (currentpin == pos)
{
pos = pinpos << 2;
/* Clear the corresponding high control register bits */
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos);
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
}
}
GPIOx->CRH = tmpreg;
}
}
我比较笨,如果是稍微聪明一点的话,很容易定位出来是上下拉的问题。我带入了PC1,需要配置成上拉输入,一步步代入,定位到这里的:
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
}
else
{
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
}
因为PC1和PC13平时都是高电平,按下为低电平,所以需要配置为上拉模式,但是GPIO的ODR寄存器的复位值是0,根据这个代码,是需要置位ODR对应引脚位。
于是程序添加这两行代码:
//PC
GPIOC->BSRR |= (1<<1);//set
GPIOC->BSRR |= (1<<13);//set
为了严谨,PA0的下拉模式配置也添加了复位代码。
GPIOC->BRR |= (1<<0);//reset
2、为什么上拉输入引脚要置位?
1)什么是上拉输入、下拉输入?
这个一搜就有答案。
2)为什么上拉输入引脚配置完要置位?
关于STM32单片机GPIO口上拉与下拉输入
我现在这水平还不能完全理解作者说的什么线与不线与啥的,但是根据“当设置上拉输入时,将其输出值设置为0,这样电平就被直接拉低了,按键的接地电路基本就不起作用了”这一句话。
我就能很能明白我聪明不到哪去。平时按键不按下为高电平,不拉高永远检测不出来什么时候按下。
写在后面
感觉自己写这些总结的时候还是过于啰嗦了,就像前辈说的不要全都总结,只总结重点的,不要把精力花在不重要的事情上。要提高效率才行。
版权声明
本文为[锂盐块呀]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_39276221/article/details/119427735
边栏推荐
猜你喜欢

LeetCode 2049. Count the number of nodes with the highest score -- traversal of the tree

Apple CMS builds a video website and collects videos regularly

CONDA command

Blue Bridge Cup 31 day sprint day14

Blue Bridge Cup 31 day sprint Day7

蓝桥杯31天冲刺 Day4

卷积神经网络

蓝桥杯31天冲刺 Day3

蓝桥杯31天冲刺 Day5

LeetCode 467. Dynamic programming -- the only substring in the surrounding string
随机推荐
Several ways to exchange two variable values without the third variable
链表的逆序输出 C语言三行代码 递归栈
05-变量及标识符
Judge whether the linked list has a ring (Set & speed pointer)
golang 合并两个有序的数组(笔试题)
telbot负载均衡设置
Deep understanding of callback functions
软件测试相关基础知识
LeetCode 467. Dynamic programming -- the only substring in the surrounding string
TCGA downloads RNA SEQ data from GBM patients
scikit-learn中的PCA
Matrix multiplication implementation
Alist easy to use guide
初学C语言用什么编译器(文章末尾有惊喜)
What compiler is used for beginners of C language (there is a surprise at the end of the article)
LeetCode 1770. Maximum score for performing multiplication -- interval DP
Introduction to machine learning -- comparison and fancy indexing in numpy
Uniapp: hbuilderx runs the uniapp project to the night God simulator
05 - variables and identifiers
本地搭建服务器后的访问问题