STM32F10x微控制器具有7个GPIO端口,分别为GPIOA、GPIOB、GPIOC、GPIOD、GPIOE、GPIOF、GPIOG,每个GPIO端口有16个I/O引脚,可配置为输入或输出,输入缓冲,输出锁存。配置寄存器GPIO_CRL和GPIO_CRH可以分别对0-7和8-15引脚进行配置,主要包括通过MODE配置为输入还是输出,通过CNF结合MODE可配置为采用输入哪种方式,输出采用哪种方式。
(1) 连接+5V电源到开发板,并打开电源开关,将ST-LINK 仿真器连接到WEEEDK嵌入式系统实验开发板的 JTAG插座上,USB 插头连接到PC的USB插口。如果没有驱动请安装ST-LNK 驱动,直到在设备管理器上看到STMicroelectronics STLink dongle为止。
(2) 复制"GPIO-LED跑马灯"文件夹中的所有内容到D盘,双击 GPIO-LED跑马灯实验的\Project\Project.uvprojx 实验工程文件,打开实验工程,阅读 main()函数。
(3) 按F7 功能键编译并链接工程。
(4) 按Ctrl+F5键或单击调试按钮,进入集成调试环境。
(5) 练习使用F10功能键单步执行、Crl+F10键执行到光标处以及F5功能键全速执行等断方式,在看执行代码后LED1~LED4指示灯的变化情况。
(6) 在全速运行时,除了观察跑马灯闪光外,还要观察外设窗口,查看相关寄存器的值及寄存器的变化。
(7) 通过改变GPIOD输出寄存器的ODR的值ODRi来管擦和LED亮灭情况
修改ODRi值,当ODRi=1时,灯灭;当ODRi=0时,灯亮
(8) 退出调试返回编辑模式,进行实验内容(2),用杜邦线连接JP13-LED5和P2-PB7,使PB7与LED5连接
连接后如下图所示
(9) 修改GPIO初试化程序,包括是能GPIOB时钟,配置PB7为10MHz推挽输出并初始化为逻辑1(LED5灭)
添加的程序块为
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /*使能PB口时钟*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;/*选择PD7引脚*/
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; /*频率10MHz*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*推挽输出*/
GPIO_Init(GPIOB, &GPIO_InitStructure); /*初始化GPIOB端口*/
/*---------初始化状态四个LED全灭OFF------------*/
GPIO_SetBits(GPIOB,GPIO_Pin_7);/*PB7输出为高电平,ED5灭*/
(10)在main()循环体中添加让LED5闪烁的代码
添加的程序块为 下面为修改后的循环体
while (1)
{
GPIO_ResetBits(GPIOD, GPIO_Pin_2); /* PD2=0 LED1亮 */
Delayms(n); /* 延时 */
GPIO_SetBits(GPIOD, GPIO_Pin_2); /* PD2=1 LED1灭 */
Delayms(n); /* 延时 */
GPIO_ResetBits(GPIOD, GPIO_Pin_3); /* PD3=0 LED2亮 */
Delayms(n); /* 延时 */
GPIO_SetBits(GPIOD, GPIO_Pin_3); /* PD3=1 LED2灭 */
Delayms(n); /* 延时 */
GPIO_ResetBits(GPIOD, GPIO_Pin_4); /* PD4=0 LED3亮 */
Delayms(n); /* 延时 */
GPIO_SetBits(GPIOD, GPIO_Pin_4); /* PD4=1 LED4灭 */
Delayms(n); /* 延时 */
GPIO_ResetBits(GPIOD, GPIO_Pin_7); /* PD7=0 LED4亮 */
Delayms(n); /* 延时 */
GPIO_SetBits(GPIOD, GPIO_Pin_7); /* PD7=1 LED4灭 */
Delayms(n); /* 延时 */
GPIO_ResetBits(GPIOB, GPIO_Pin_7); /* PB7=0 LED5亮 */
Delayms(n); /* 延时 */
GPIO_SetBits(GPIOB, GPIO_Pin_7); /* PB7=1 LED5灭 */
Delayms(n); /* 延时 */
}
(11)按F7键编译并链接,然后排除所有错误,最后编译链接
(12)按CTRL+F5进入调试环境
(13)按F5功能键运行程序,查看跑马灯显示是否正确,不正确的话修改代码,继续调试到正确为止。运行时观察GPIOB窗口输出寄存器的变化
(14)试着改变闪光时间,观察显示效果
修改以下函数即可
#define n 500 /*延时时间常数*/
void Delayms(uint16_t N)
{
uint32_t i;
for (i = 0; i < (8000 * N); i++)
;
}
(15)请用寄存器操作方法实现LED1~LED5跑马灯显示
按下面所示方式进行修改即可
GPIOD->ODR &= ~(1<<2) //让LED1亮
GPIOD->ODR |= (1<<2) //让LED1灭
(16)使用汇编语言让LED1闪烁
添加下面的两个函数
__asm LED10() //LED1 亮
{
LDR R0, = 0X4001140C;
LDRH R1, [R0];
LDR R2, = 0XFFFFFFFB;
AND R1, R1, R2;
STRH R1, [R0];
BX LR;
}
__asm LED11() //LED1 灭
{
LDR R0, = 0X4001140C;
LDRH R1, [R0];
LDR R2, = 0X00000004;
ORR R1, R1, R2;
STRH R1, [R0];
BX LR;
}
在主函数里调用即可
int main(void)
{
// SystemInit(); //系统初始化,此处可以省,因为在启动文件中有该函数的调用
GPIO_LED_Init(); // GPIO初始化
while (1)
{
LED10();
Delayms(n);
LED11();
Delayms(n);
}
}
初始代码
/************************************************************************************
** WEEEDK NUAA_CM3_107实验开发板(V4.1/V4.2)
** GPIO-LED应用跑马灯实验
** 操作及现象:下载程序运行后看到四个LED指示灯闪光(轮流亮灭,似跑马灯)
** 版 本:V4.1
** 作 者:NUAA
** 完成日期: 2017.3.18
************************************************************************************/
#include "stm32f10x_conf.h"
/*********************************************
*函数名称:void Delayms(void)
*
*入口参数:N ms
*
*出口参数:无
*
*功能说明:简单延时N ms
**********************************************/
#define n 500 /*延时时间常数*/
void Delayms(uint16_t N)
{
uint32_t i;
for (i = 0; i < (8000 * N); i++)
;
}
void GPIO_LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); /*使能PD口时钟*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7; /*选择PD2/PD3/PD4/PD7引脚*/
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; /*频率10MHz*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*推挽输出*/
GPIO_Init(GPIOD, &GPIO_InitStructure); /*初始化GPIOD端口*/
/*---------初始化状态四个LED全灭OFF------------*/
GPIO_SetBits(GPIOD, GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7); /*PD2/PD3/PD4/PD7输出为高电平,四LED全灭*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /*使能PB口时钟*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; /*选择PD7引脚*/
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; /*频率10MHz*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*推挽输出*/
GPIO_Init(GPIOB, &GPIO_InitStructure); /*初始化GPIOB端口*/
GPIO_SetBits(GPIOB, GPIO_Pin_7); /*PB7输出为高电平,ED5灭*/
}
__asm LED10()
{
LDR R0, = 0X4001140C;
LDRH R1, [R0];
LDR R2, = 0XFFFFFFFB;
AND R1, R1, R2;
STRH R1, [R0];
BX LR;
}
__asm LED11()
{
LDR R0, = 0X4001140C;
LDRH R1, [R0];
LDR R2, = 0X00000004;
ORR R1, R1, R2;
STRH R1, [R0];
BX LR;
}
int main(void)
{
// SystemInit(); //系统初始化,此处可以省,因为在启动文件中有该函数的调用
GPIO_LED_Init(); // GPIO初始化
while (1)
{
// GPIO_ResetBits(GPIOD, GPIO_Pin_2); /* PD2=0 LED1亮 */
// Delayms(n); /* 延时 */
// GPIO_SetBits(GPIOD, GPIO_Pin_2); /* PD2=1 LED1灭 */
// Delayms(n); /* 延时 */
// GPIO_ResetBits(GPIOD, GPIO_Pin_3); /* PD3=0 LED2亮 */
// Delayms(n); /* 延时 */
// GPIO_SetBits(GPIOD, GPIO_Pin_3); /* PD3=1 LED2灭 */
// Delayms(n); /* 延时 */
// GPIO_ResetBits(GPIOD, GPIO_Pin_4); /* PD4=0 LED3亮 */
// Delayms(n); /* 延时 */
// GPIO_SetBits(GPIOD, GPIO_Pin_4); /* PD4=1 LED4灭 */
// Delayms(n); /* 延时 */
// GPIO_ResetBits(GPIOD, GPIO_Pin_7); /* PD7=0 LED4亮 */
// Delayms(n); /* 延时 */
// GPIO_SetBits(GPIOD, GPIO_Pin_7); /* PD7=1 LED4灭 */
// Delayms(n); /* 延时 */
// GPIO_ResetBits(GPIOB, GPIO_Pin_7); /* PB7=0 LED5亮 */
// Delayms(n); /* 延时 */
// GPIO_SetBits(GPIOB, GPIO_Pin_7); /* PB7=1 LED5灭 */
// Delayms(n); /* 延时 */
LED10();
Delayms(n);
LED11();
Delayms(n);
}
}
(1) 连接+5V电源到开发板,并打开电源开关,将ST-LINK 仿真器连接到WEEEDK嵌入式系统实验开发板的 JTAG插座上,USB 插头连接到PC的USB插口。如果没有驱动请安装ST-LNK 驱动,直到在设备管理器上看到STMicroelectronics STLink dongle为止。
(2) 复制"GPIO-KEYLED跑马灯"文件夹中的所有内容到D盘,双击 GPIO-LED跑马灯实验的\Project\Project.uvprojx 实验工程文件,打开实验工程,阅读 main()函数。
(3) 按F7 功能键编译并链接工程。
(4) 按Ctrl+F5键或单击调试按钮,进入集成调试环境。
(5)按F5功能键全速执行。查看执行代码后LED1~LED4知识灯的变化情况。在没有任何操作时,与跑马灯效果已有,4个LED闪光二极管依次发光
(6)分别按KEY1、KEY2、KEY3和KEY4键 ,观察LED1、LED2、LED3、LED4显示情况
连接图如下所示
(7)添加代码时每按一下按键时均有一声响声
退出调试环境,返回编辑模式,添加代码,完成在按键时让蜂鸣器响一声。需要短接JP12,将PC0与蜂鸣器控制电路相连。
添加的代码为
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure); /*初始化GPIOC端口推挽输出,50MHz*/
GPIO_ResetBits(GPIOC, GPIO_Pin_0); //PC0=0,此时蜂鸣器不响
新建一个Beep()
函数,功能是响一声,代码如下
void Beep(void)
{
GPIO_SetBits(GPIOC, GPIO_Pin_0);
Delayms(n);
GPIO_ResetBits(GPIOC, GPIO_Pin_0);
}
在main()
中修改
int main(void)
{
u8 KEY = 0;
u8 i = 0;
u16 Pinx[4] = {GPIO_Pin_2, GPIO_Pin_3, GPIO_Pin_4, GPIO_Pin_7};
SystemInit(); /* 系统初始化 */
GPIO_KEYLED_Init(); /* GPIO初始化 */
while (1)
{
if (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_11) == 0)
{
KEY = 1;
Beep();
}
else
{
if (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_12) == 0)
{
KEY = 2;
Beep();
}
else
{
if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13) == 0)
{
KEY = 3;
Beep();
}
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0)
{
KEY = 4;
Beep();
}
}
}
if (KEY == 0)
{
GPIO_ResetBits(GPIOD, Pinx[i]); /* LEDi+1亮 */
Delayms(n); /* 延时n ms */
GPIO_SetBits(GPIOD, Pinx[i]); /* LEDi+1灭 */
Delayms(n);
i++;
if (i >= 4)
i = 0;
}
else
{
GPIO_ResetBits(GPIOD, Pinx[KEY - 1]);
/* LED[KEY-1]亮 */
Delayms(n); /* 延时n ms */
GPIO_SetBits(GPIOD, Pinx[KEY - 1]);
/* LED[KEY-1]灭 */
Delayms(n);
}
}
}
(8)按F7键编译并链接,然后排除所有错误,最后编译链接
(9)按CTRL+F5进入调试环境
(10)按F5功能键运行程序,查看跑马灯显示是否正确,不正确的话修改代码,继续调试到正确为止。
(11)除了初始化程序外,将上述采用固件库函数操作代码修改为寄存器操作的代码
添加的代码为
GPIOD->ODR &= ~(1<<2) //让蜂鸣器不响
GPIOD->ODR |= (1<<2) //让蜂鸣器响
在没有按键按下时,让双色灯灭;当KEY1按下时,双色灯LED7发红光,且电机正转;当KEY2按下时双色灯LED7发绿光,且电机反转;当KEY3按下时LED7灭,电机停止运转。
(1)连接 +5V电源到开发板,将ST-LINK仿真器连接到WEEEDK嵌入式系统实验开发板的JTAG插座上,USB插头连接到PC的USB插口;
(2)复制”GPIO-MOTO”文件夹的所有内容到D盘,双击…\Project\Project.uvprojx实验工程文件,打开实验工程,找到main()函数。
(3)按F7功能键编译并链接工程。
(4)按Ctrl+F5 键或单击调试按钮,进入集成调试环境。使用F10功能键单步调试、Ctrl+F10执行到光标处、F5功能键全力执行。在全速运行时,要观察LED7和电机运行情况。
(5)分别按KEY1、KEY2、KEY3,观察LED7和电机运行情况。
按KEY1:
按KEY2:
按KEY3: LED7熄灭,电机不转。
(6)返回编辑模式,修改或添加代码,完成由PE14和PE15分别控制电机的正转和反转。
拔下JP5、JP6,并用杜邦线将P1中的PE14连接到JP5-3脚,让PE15连接到JP6-3脚,让PE14连接到IA,让PE15连接到IB。
修改GPIO初始化程序GPIO_MOTO_Init()
#define IA(x) ((x) ? (GPIO_SetBits(GPIOB, GPIO_Pin_14)) : (GPIO_ResetBits(GPIOB, GPIO_Pin_14)))
#define IB(x) ((x) ? (GPIO_SetBits(GPIOB, GPIO_Pin_15)) : (GPIO_ResetBits(GPIOB, GPIO_Pin_15)))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure); /*初始化GPIOE端口PB14=IA,PB15=IB 50MHz推挽输出*/
(7)按F7编译并链接,然后排除所有错误,最后编译链接。
(8)按Ctrl+F5进入调试环境。
(9)按F5功能键运行程序,查看程序运行是否正确。如果不正确,就修改代码,继续调试,直到正确为止。
通过添加代码成功实现让LED1、LED2、LED3、LED4、LED5轮流闪光,分别使用固件库函数方法,寄存器操作方法,以及汇编语言方法。具体的代码部分请参照上一节中的内容。
实验结果图片:
通过添加代码成功实现按下任意键,蜂鸣器均响一声,分别使用了固件库函数方法,寄存器操作方法。具体的代码部分请参照上一节中的内容。
实验结果图片:
这次实验成功实现了当KEY1按下时LED7发红光、电机正转,当KEY2按下时LED7发绿光、电机反转,当KEY2按下时,LED7灭、电机停止;修改GPIO初始化程序和相关程序、改变硬件的连接后也能得到相同的结果,达到了预期的实验效果。