打印
[KungFu32位 MCU]

KF32F341的IO输入功能

[复制链接]
9296|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
关于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采样功能无恙

希望各位老哥能提供下帮助呀

使用特权

评论回复
评论
psm132132 2021-7-8 13:37 回复TA
IO的时钟在芯片上电时就默认开启, 所以只是普通的IO操作, 可以不用关注时钟. GPIO_Reset()这个函数不需要调用. 
沙发
yangxiaor520| | 2021-7-6 17:36 | 只看该作者
上代码看看

使用特权

评论回复
板凳
taozhi11|  楼主 | 2021-7-6 21:14 | 只看该作者

#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);
                }

        }

        }               
}

使用特权

评论回复
地板
编号10086| | 2021-7-8 12:46 | 只看该作者
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没有配置成输入模式。

使用特权

评论回复
5
编号10086| | 2021-7-8 12:49 | 只看该作者
我参考官方的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);
应该就可以了。

使用特权

评论回复
6
编号10086| | 2021-7-8 12:57 | 只看该作者
官方例程中用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寄存器应该不是你要的那种配置的。

使用特权

评论回复
评论
taozhi11 2021-7-8 18:24 回复TA
我还是对库函数太过依赖了,这次也是认识到了自己的不足了,再次感谢老哥 
7
taozhi11|  楼主 | 2021-7-8 18:13 | 只看该作者
编号10086 发表于 2021-7-8 12:57
官方例程中用gpio_reset作为时钟使能。你看官方的这个代码

太感谢老哥这么认真的回复我了,确实是RESET的问题,我把第二个RESET函数注释掉就可以跑通了。这个例程在老芯片上跑是没问题的,应该是老板子IO没有全部复位?导致我一致认为这个例程是没问题的。感谢感谢

使用特权

评论回复
8
编号10086| | 2021-7-9 13:41 | 只看该作者
更正一点,那个复位寄存器RST_CTLX,是需要配置的。
我提供的api,GPIO_CLK_CTL里面没有加,但是却能够正常使用。
是因为RST_CTL0复位值就是0,而其他的是1。
所以我在今天改写spi例程的时候,突然发现用不来了。


所以总结得出芯旺微单片机要使能某个时钟的话,需要两步
1.把对应的 RST_CTLX 寄存器 置0.
2.把对应的 PCLK_CTLX寄存器 置1.

之前配置GPIO的时候第一步没有做,不过阴差阳错,正好复位状态它就是0,所以使用起来还没什么影响。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

10

帖子

0

粉丝