当前位置: 首页 > news >正文

STM32F103复用JTAG/SWD引脚为GPIO

普中-精灵1开发板,主芯片为STM32F103C8T6,4个独立按键K1~K4依次接PA15~PA12,按下为低电平,8个LED灯D1~D8,依次接PA0~PA7。查询手册得知:PA15主功能为JTDI,PA14为JTCK/SWCLK,PA13为JTMS/SWDIO。采用串口进行程序下载(普中ISP)。用4个按键,控制4个LED,主程序如下:

/*按键程序,普中-精灵1开发板*/
#include "stm32f10x.h"
#include "delay.h"
#include "key.h"
int main(void)
{ 
	KEY_Init();
    // 初始化 LED 亮灭标志为 0      0:熄灭    1:亮起
   unsigned int led_flag1 = 0;
   unsigned int led_flag2 = 0;
   unsigned int led_flag3 = 0;
   unsigned int led_flag4 = 0;
    // 初始化 按键按下标志为 0      0:弹起    1:按下
    unsigned int key_is_press1 = 0;
    unsigned int key_is_press2 = 0;
    unsigned int key_is_press3 = 0;
    unsigned int key_is_press4 = 0;
   while (1)
    { 
        if( key_is_press1 == 0)  //无按键
        {
            if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) ==0)
            {   // 如果按键按下
                Delay(20); // 按键消抖
                if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15)==0 )
                {   // 如果按键被按下,设置按键按下标志为 1
                    key_is_press1 = 1;
                    // 设置 LED 亮灭标志翻转一次
                    led_flag1 = ~led_flag1;
                }
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press1 = 0;
            }
        }
        else    // 如果按键已经按下了,判断按键是否弹起
        {
            if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15)==0 )
            {   // 按键仍然处于按下状态,不进行任何操作
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press1 = 0;
            }
					}	
   if( key_is_press2 == 0)
        {
            if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14) ==0)
            {   // 如果按键按下
                Delay(20); // 按键消抖
                if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14)==0 )
                {   // 如果按键被按下,设置按键按下标志为 1
                    key_is_press2 = 1;
                    // 设置 LED 亮灭标志翻转一次
                    led_flag2 = ~led_flag2;
                }
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press2 = 0;
            }
        }
        else    // 如果按键已经按下了,判断按键是否弹起
        {
            if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14)==0 )
            {   // 按键仍然处于按下状态,不进行任何操作
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press2 = 0;
            }			
						
        }				
   if( key_is_press3 == 0)
        {
            if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13) ==0)
            {   // 如果按键按下
                Delay(20); // 按键消抖
                if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13)==0 )
                {   // 如果按键被按下,设置按键按下标志为 1
                    key_is_press3 = 1;
                    // 设置 LED 亮灭标志翻转一次
                    led_flag3 = ~led_flag3;
                }
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press3 = 0;
            }
        }
        else    // 如果按键已经按下了,判断按键是否弹起
        {
            if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13)==0 )
            {   // 按键仍然处于按下状态,不进行任何操作
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press3 = 0;
            }			
        }
 if( key_is_press4 == 0)
        {
            if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) ==0)
            {   // 如果按键按下
                Delay(20); // 按键消抖
                if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12)==0 )
                {   // 如果按键被按下,设置按键按下标志为 1
                    key_is_press4 = 1;
                    // 设置 LED 亮灭标志翻转一次
                    led_flag4 = ~led_flag4;
                }
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press4 = 0;
            }
        }
        else    // 如果按键已经按下了,判断按键是否弹起
        {
            if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12)==0 )
            {   // 按键仍然处于按下状态,不进行任何操作
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press4 = 0;
            }			
        }
        
        // 根据按键按下的标志状态操作功能
        // 如果按键被按下了,执行功能
        if( key_is_press1 == 1)
        {   
	// 根据 LED 的亮灭标志控制 LED 亮起和熄灭
            if(led_flag1)
            {
                // 点亮 LED
                GPIO_ResetBits(GPIOA, GPIO_Pin_0 ); 
            }
            else
            {
                // 熄灭 LED
                GPIO_SetBits(GPIOA, GPIO_Pin_0 ); 
            }               
        }

 if( key_is_press2 == 1)
        {   // 根据 LED 的亮灭标志控制 LED 亮起和熄灭
            if(led_flag2)
            {
                // 点亮 LED
                GPIO_ResetBits(GPIOA, GPIO_Pin_1 ); 
            }
            else
            {
                // 熄灭 LED
               GPIO_SetBits(GPIOA, GPIO_Pin_1 ); 
            }               
        }	
 if( key_is_press3 == 1)
        {   // 根据 LED 的亮灭标志控制 LED 亮起和熄灭
            if(led_flag3)
            {
                // 点亮 LED
               GPIO_ResetBits(GPIOA, GPIO_Pin_2 ); 
            }
            else
            {
                // 熄灭 LED
              GPIO_SetBits(GPIOA, GPIO_Pin_2 ); 
            }               
        }	
			  if( key_is_press4 == 1)
        {   // 根据 LED 的亮灭标志控制 LED 亮起和熄灭
            if(led_flag4)
            {
                // 点亮 LED
                GPIO_ResetBits(GPIOA, GPIO_Pin_3 ); 
            }
            else
            {
                // 熄灭 LED
                GPIO_SetBits(GPIOA, GPIO_Pin_3 ); 
            }               
        }					
				
    }
			
}

按键初始化程序key.c如下:

/*key.c按键初始化
*/
#include "key.h"
#include "delay.h"
void KEY_Init(void)
{ 
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);  // 开启时钟
  //GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;       //配置GPIO频率为50MHz
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15 ;	
  //GPIO_SetBits(GPIOA, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_SetBits(GPIOA, GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3); 
}

执行以上,会发现K1、K3、K4功能正常,而K2(PA14)无效,此时D2(PA1)常亮,按照手册,若此时禁掉SWD,即去掉GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);前面的注释,此时并无效果,反而有可能出现K1(PA15)、K3(PA13)也失效的情形。此时,需要执行非常关键的一个操作,即对PA12、PA13、PA14、PA15置1,且要在设置MODE之前进行,去掉GPIO_SetBits(GPIOA, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);前面的注释,会发现K2功能也正常了。实际上,如果用CMSIS-DAP(实际为WCH CMSIS-DAP,SW模式,BOOT0=1)下载程序,不需要增加GPIO_SetBits(GPIOA, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);这条指令,K2功能也是正常的。但神奇的是,利用JTAG(实际为J-Link ARM-OB STM32,SW模式,BOOT0=1),则和ISP方式效果一致。

在普中的这款开发板做进一步开发,例如把按键和数码管结合起来,按K1数码管显示加1,按K2减1,按K3数码管左移1位,按K4数码管右移1位。,主程序如下:

/*按键驱动数码管,普中-精灵1开发板*/
#include "stm32f10x.h"
#include "delay.h"
#include "key.h"
uint16_t table[] = {0xFF3F,0xFF06,0xFF5b,0xFF4f,0xFF66,0xFF6d,0xFF7d,0xFF07,0xFF7f,0xFF6f}; //段码
uint16_t  wei[]={0xff00,0xff20,0xff10,0xff30,0xff08,0xff28,0xff18,0xff38}; //位码
static uint8_t k=0;  //声明变量 k,j
static uint8_t j=0;
int main(void)
{   KEY_Init();
    unsigned int key_is_press1 = 0;
    unsigned int key_is_press2 = 0;
    unsigned int key_is_press3 = 0;
    unsigned int key_is_press4 = 0;
    while (1)
    { 
        if( !key_is_press1)  //无按键
        {
            if( !GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15))
            {   // 如果按键按下
                Delay(20); // 按键消抖
                if( !GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) )
                {   // 如果按键被按下,设置按键按下标志为 1
                    key_is_press1 = 1;
			  	    j=j+1;
                }
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press1 = 0;
            }
        }
        else    // 如果按键已经按下了,判断按键是否弹起
         {
           if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) ) //按键弹起,设置按键按下标志为 0
           key_is_press1 = 0;
    	 }	
   if( !key_is_press2)
        {
            if( !GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14))
            {   // 如果按键按下
                Delay(20); // 按键消抖
                if( !GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14))
                {   // 如果按键被按下,设置按键按下标志为 1
                    key_is_press2 = 1;
  					j=j-1;
                }
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press2 = 0;
            }
        }
        else    // 如果按键已经按下了,判断按键是否弹起
        {
           if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14) ) // 按键弹起,设置按键按下标志为 0
           key_is_press2 = 0;
	        }				
   if( !key_is_press3 )
        {
            if( !GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13))
            {   // 如果按键按下
                Delay(20); // 按键消抖
                if( !GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13))
                {   // 如果按键被按下,设置按键按下标志为 1
                    key_is_press3 = 1;
				    k++;
                }
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press3 = 0;
            }
        }
        else    // 如果按键已经按下了,判断按键是否弹起
        {
           if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13) ) // 按键弹起,设置按键按下标志为 0
           key_is_press3 = 0;
	        }
	 if(!key_is_press4 )
        {
            if( !GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12))
            {   // 如果按键按下
                Delay(20); // 按键消抖
                if( !GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) )
                {   // 如果按键被按下,设置按键按下标志为 1
                    key_is_press4 = 1;
		            k--;
                }
            }
            else
            {   // 如果按键弹起,设置按键按下标志为 0
                key_is_press4 = 0;
            }
        }
        else    // 如果按键已经按下了,判断按键是否弹起
        {
          if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) ) // 按键弹起,设置按键按下标志为 0
              key_is_press4 = 0;
		 }
   GPIO_Write(GPIOA,table[j%8] );
   GPIO_Write(GPIOB, wei[k%8] );
	  }
}

段码数组要32位数赋值,因为GPIO_Write(GPIOA,...)默认情况下是对整个PA进行操作,如果只给出16位数,那么高16位数将被赋值为0,显然这样就有可能导致读数据失败。参考按键初始化程序:

/*key.c
按键初始化
*/
#include "key.h"
#include "delay.h"
void KEY_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);  // 开启时钟
  GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;       //配置GPIO频率为50MHz
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15 ;	
	GPIO_SetBits(GPIOA, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; 
	GPIO_SetBits(GPIOA, GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
 	GPIO_Init(GPIOA, &GPIO_InitStructure); 
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

 

 

相关文章:

  • 数学建模:针对汽车行驶工况构建思路的延伸应用
  • 大模型SFT用chat版还是base版 SFT后灾难性遗忘怎么办
  • 大模型常见面试题
  • 上篇:新能源轻卡城配物流经济/动力模式量化定义(理论篇)——数学暴力破解工程困局
  • 十六、Linus网络编程基础
  • 【学习笔记】服务器上使用 nbconvert 将 Jupyter Notebook 转换为 PDF
  • 北邮LLMs在导航中的应用与挑战!大模型在具身导航中的应用进展综述
  • go语言内存泄漏的常见形式
  • Day-03 前端 Web-Vue Axios 基础
  • docker部署scylladb
  • 鲁大师绿色版,纯净无广告
  • 统计当前页面的localStorage使用了多少空间
  • FATFS文件系统配置
  • Sa-Token v1.42.0 发布 [特殊字符],新增 API Key、TOTP 验证码、RefreshToken 反查等能力
  • NOIP2015提高组.运输计划
  • Web 项目实战:构建属于自己的博客系统
  • 雷池WAF防火墙如何构筑DDoS防护矩阵?——解读智能语义解析对抗新型流量攻击
  • 数据库预热
  • PostIn安装及入门教程
  • 初识华为防火墙
  • 网站建设项目分期/厦门网站到首页排名
  • 网站的代理页面怎么做/在线数据分析工具
  • 广州手机网站定制信息/浙江搜索引擎优化
  • 刷信誉网站制作/淘宝seo优化怎么做
  • 李沧做网站/制作公司网站
  • wordpress插件没有设置/深圳百度首页优化