KF32F341的IO输入功能
关于IO口输入(按键)失灵的分析采用的是KF32F350的官方例程,移植到KF34F341的板子上出现了问题
预期实现:供电后LED亮,按下按键后LED状态翻转
硬件:
1.按下按键后并无反应
2.万用表测量按键一端电压,有0->3.3V电压状态改变
3.直接将3.3V电压接触实现按键的芯片引脚,LED也无现象
4.改代码,用其他IO口做输入,仍无响应
5.换了另一块341的板子也不可以
软件:
1.将该程序烧入至F350开发板,板子能正确工作,LED正常反转
2.换用按键中断程序,代码不能正常工作,将IO输入的函数注释掉后可以正常工作
3.经实测IO口的输出以及模拟输入功能正常,如LED闪烁,ADC采样功能无恙
希望各位老哥能提供下帮助呀 上代码看看 yangxiaor520 发表于 2021-7-6 17:36
上代码看看
#include "system_init.h"
#define KEY2 GPIO_Read_Input_Data_Bit(GPIOA_SFR,GPIO_PIN_MASK_3)
//延时函数 局部变量用volatile声明,否则可能会被优化
//主频时120M 1ms延时函数
void delay_ms(volatile uint32_t nms)
{
volatile uint32_t i,j;
for(i=0;i<nms;i++)
{
j=700;
while(j--);
}
}
/**
* 描述GPIOx 输出初始化配置。
* 输入 : GPIOx: 指向GPIO内存结构的指针,取值为GPIOA_SFR~GPIOH_SFR。
* GpioPin: 端口引脚掩码,取值为GPIO_PIN_MASK_0~GPIO_PIN_MASK_15中的一个或多个组合。
* 返回无。
*/
void GPIOInit_Output_Config(GPIO_SFRmap* GPIOx,uint16_t GpioPin)
{
/*初始化复位GPIOx外设,使能GPIOx外设时钟*/
GPIO_Reset(GPIOx);
/* 配置 Pxy作为输出模式参数 */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_Struct_Init(&GPIO_InitStructure);
GPIO_InitStructure.m_Pin = GpioPin;
GPIO_InitStructure.m_Speed = GPIO_LOW_SPEED; //初始化 GPIO输出速度
GPIO_InitStructure.m_Mode = GPIO_MODE_OUT; //初始化 GPIO方向为输出
GPIO_InitStructure.m_PullUp = GPIO_NOPULL; //初始化 GPIO是否上拉
GPIO_InitStructure.m_PullDown = GPIO_NOPULL; //初始化 GPIO是否下拉
GPIO_Configuration(GPIOx,&GPIO_InitStructure);
GPIO_Set_Output_Data_Bits(GPIOx,GpioPin,Bit_SET); //先设置为高电平
}
/**
* 描述GPIOx 输入初始化配置。
* 输入 : GPIOx: 指向GPIO内存结构的指针,取值为GPIOA_SFR~GPIOH_SFR。
* GpioPin: 端口引脚掩码,取值为GPIO_PIN_MASK_0~GPIO_PIN_MASK_15中的一个或多个组合。
* 返回无。
*/
void GPIOInit_Input_Config(GPIO_SFRmap* GPIOx,uint16_t GpioPin)
{
/*初始化复位GPIOx外设,使能GPIOx外设时钟*/
GPIO_Reset(GPIOx);
/* 配置 Pxy作为输入模式 */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_Struct_Init(&GPIO_InitStructure);
GPIO_InitStructure.m_Pin = GpioPin;
GPIO_InitStructure.m_Speed = GPIO_LOW_SPEED; //初始化 GPIO输出速度
GPIO_InitStructure.m_Mode = GPIO_MODE_IN; //初始化 GPIO方向为输入
GPIO_InitStructure.m_PullUp = GPIO_NOPULL; //初始化 GPIO是否上拉 不上拉
GPIO_InitStructure.m_PullDown = GPIO_NOPULL; //初始化 GPIO是否下拉 不下拉
GPIO_Configuration(GPIOx,&GPIO_InitStructure);
}
/**
* 描述GPIOx 输入与输出初始化配置。
* 输入 : 无
* 返回无。
*/
void GPIO_Init(void)
{
GPIOInit_Input_Config(GPIOA_SFR,GPIO_PIN_MASK_3);
GPIOInit_Output_Config(GPIOA_SFR,GPIO_PIN_MASK_8|GPIO_PIN_MASK_7);//PB8 PB9 PB10初始化输出高电平
}
//主函数
void main()
{
/*用户可参考该例程在KF32F350_demo板上实现GPIO输入配置功能。
* 例程中使用GPIO PD6作为按键的输入IO PB8 PB9 PB10作为输出
* 按键KEY2按下,LED0 LED1灯熄灭,再次按下LED0 LED1灯点亮。
*/
//系统时钟120M,外设高频时钟16M
SystemInit();//系统时钟初始化
//GPIO初始化
GPIO_Init(); //把PD6设为输入模式 PB8 PB9 PB10初始化输出高电平
while(1)
{
if(KEY2)
{
delay_ms(50); //延时50ms抖动
if(KEY2) //有按键按下
{
GPIO_Toggle_Output_Data_Config (GPIOA_SFR,GPIO_PIN_MASK_8);
GPIO_Toggle_Output_Data_Config (GPIOA_SFR,GPIO_PIN_MASK_7);
}
}
}
} GPIOInit_Input_Config(GPIOA_SFR,GPIO_PIN_MASK_3);
GPIOInit_Output_Config(GPIOA_SFR,GPIO_PIN_MASK_8|GPIO_PIN_MASK_7);//PB8 PB9 PB10初始化输出高电平
这两句话官方的api中都调用了GPIO_Reset(GPIOx);这个函数
经过我的测试,这个函数会把GPIOA管脚的配置都复位掉。
也就是你这样写GPIOInit_Input_Config(GPIOA_SFR,GPIO_PIN_MASK_3);
GPIOInit_Output_Config(GPIOA_SFR,GPIO_PIN_MASK_8|GPIO_PIN_MASK_7);
实际上只有后面的PA7,PA8配置成了输出模式。而PA3没有配置成输入模式。 我参考官方的api,自己写了 一个时钟使能的函数。
/*
*********************************************************************************************************
*函数名:GPIO_CLK_CTL
*功能说明:初始化CLK时钟
*形参:GPIOx:代表某组管脚,NewState:代表是否使能
*返回值:无
*********************************************************************************************************
*/
void GPIO_CLK_CTL(GPIO_SFRmap* GPIOx, FunctionalState NewState)
{
/* 参数校验 */
CHECK_RESTRICTION(CHECK_GPIO_ALL_PERIPH(GPIOx));
if (GPIOx == GPIOA_SFR)
{
PCLK_CTL0_Peripheral_Clock_Enable(PCLK_CTL0_GPIOACLKEN, NewState);
}
else if (GPIOx == GPIOB_SFR)
{
PCLK_CTL0_Peripheral_Clock_Enable(PCLK_CTL0_GPIOBCLKEN, NewState);
}
else if (GPIOx == GPIOC_SFR)
{
PCLK_CTL0_Peripheral_Clock_Enable(PCLK_CTL0_GPIOCCLKEN, NewState);
}
else if (GPIOx == GPIOD_SFR)
{
PCLK_CTL0_Peripheral_Clock_Enable(PCLK_CTL0_GPIODCLKEN, NewState);
}
else if (GPIOx == GPIOE_SFR)
{
PCLK_CTL0_Peripheral_Clock_Enable(PCLK_CTL0_GPIOECLKEN, NewState);
}
else if (GPIOx == GPIOF_SFR)
{
PCLK_CTL0_Peripheral_Clock_Enable(PCLK_CTL0_GPIOFCLKEN, NewState);
}
else if (GPIOx == GPIOG_SFR)
{
PCLK_CTL0_Peripheral_Clock_Enable(PCLK_CTL0_GPIOGCLKEN, NewState);
}
else if (GPIOx == GPIOH_SFR)
{
PCLK_CTL0_Peripheral_Clock_Enable(PCLK_CTL0_GPIOHCLKEN, NewState);
}
else
{
;
}
}
你把 GPIO_Reset(GPIOx);替换成我的这个GPIO_CLK_CTL(GPIOx,ENABLE);应该就可以了。 官方例程中用gpio_reset作为时钟使能。你看官方的这个代码
/**
* 描述复位GPIO外设,使能外设时钟。
* 输入GPIOx: 指向GPIO内存结构的指针,取值为GPIOA_SFR~GPIOH_SFR。
* 返回无。
*/
void
GPIO_Reset (GPIO_SFRmap* GPIOx)
{
/* 参数校验 */
CHECK_RESTRICTION(CHECK_GPIO_ALL_PERIPH(GPIOx));
if (GPIOx == GPIOA_SFR)
{
RST_CTL0_Peripheral_Reset_Enable(RST_CTL0_GPIOARST, TRUE);
RST_CTL0_Peripheral_Reset_Enable(RST_CTL0_GPIOARST, FALSE);
PCLK_CTL0_Peripheral_Clock_Enable(PCLK_CTL0_GPIOACLKEN, TRUE);
}
它还配置了GPIOxRST这个寄存器,不知道为什么官方要这么做..
而且它其他的串口,定时器的时钟使能也是用类似的做法实现的。
stm32的话不用配置,也能读取IDR寄存器,但是我测试芯旺微的KF32,你要读取PIR寄存器的话,必须把这个管脚配置成输入模式。
你自己debug模式下,看功能寄存器的值,看看pmod是不是配置成你要的。用官方的api配置的话,我看贴的那个代码,应该pmod寄存器应该不是你要的那种配置的。
编号10086 发表于 2021-7-8 12:57
官方例程中用gpio_reset作为时钟使能。你看官方的这个代码
太感谢老哥这么认真的回复我了{:handshake:}{:handshake:},确实是RESET的问题,我把第二个RESET函数注释掉就可以跑通了。这个例程在老芯片上跑是没问题的,应该是老板子IO没有全部复位?导致我一致认为这个例程是没问题的。{:handshake:}感谢感谢 更正一点,那个复位寄存器RST_CTLX,是需要配置的。
我提供的api,GPIO_CLK_CTL里面没有加,但是却能够正常使用。
是因为RST_CTL0复位值就是0,而其他的是1。
所以我在今天改写spi例程的时候,突然发现用不来了。
所以总结得出芯旺微单片机要使能某个时钟的话,需要两步
1.把对应的 RST_CTLX 寄存器 置0.
2.把对应的 PCLK_CTLX寄存器 置1.
之前配置GPIO的时候第一步没有做,不过阴差阳错,正好复位状态它就是0,所以使用起来还没什么影响。。
页:
[1]