注:本文以STM32F103R6为例,用keil5编程,用proteus8.1来展示结果。
1. 首先如图所示在proteus中画好原理图,要注意的是电阻不易过大,电阻过大,电阻上分压过多,会导致LED很暗或者点不亮!
2. 编写和讲解代码
a. 首先讲解LED配置文件,图中的led.c文件
解释如下:
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;//定义一个结构体变量,名字为GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//GPIOA引脚使能,即启动PA的时钟
//给结构体的成员变量赋值
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//定义GPIO引脚的模式为输出模式
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;//定义操作的引脚为第0号引脚,
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//工作频率
GPIO_Init(GPIOA,&GPIO_InitStruct);//PA0 对PA0进行初始化
}
问:为什么led.c中定义的是第0号引脚?
答:因为原理图中LED灯接的是引脚PA0;
b.编写让LED点亮的代码:在main.c中写入
int main(void)
{
int i = 0;
LED_GPIO_Config();//LED初始化
while(1)//死循环
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//功能 清零 PA0 LED亮
main_delay(200);//延时,软件延时cpu空跑循环
GPIO_SetBits(GPIOA,GPIO_Pin_0);//功能:置1 PA0 LED灭
main_delay(200);//延时
}
}
注:这里的GPIO_ResetBits()函数是清零,GPIO_SetBits()函数是置1
如此,简单的点亮LED灯就实现了!
解释:原理图中LED分别接在了PA0和PA6,所以在led.c中要同时定义PA0和PA6
问:同时定义PA0和PA6,问什么是GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_6;这里面的GPIO_Pin_0 | GPIO_Pin_6怎么理解?
答:本文中的STM32单片机有GPIOA,GPIOB,GPIOC三组引脚,每组有16个引脚,所以个引脚都是由16位2进制数来控制的。
如:
0000000000000001,表示第0个引脚,;
0000000000000010,表示第1个引脚;
0000000000000100,表示第2个引脚;
……
1000000000000000,表示第16个引脚;
所以,同时定义PA0和PA6即GPIO_Pin_0 | GPIO_Pin_6=0000000001000001
在main.c中编写代码:
int main(void)
{
int i = 0;
LED_GPIO_Config();//LED初始化
while(1)//死循环
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//功能 清零 PA0 黄LED亮
GPIO_SetBits(GPIOA,GPIO_Pin_6);//功能:置1 PA6 红LED灭
main_delay(200);//延时,软件延时cpu空跑循环
GPIO_SetBits(GPIOA,GPIO_Pin_0);//功能:置1 PA0 黄LED灭
GPIO_ResetBits(GPIOA,GPIO_Pin_6);//功能 清零 PA6 红LED亮
main_delay(200);//延时
}
}
对题目的解释:
如原理图中的绿灯、蓝灯、红灯、黄灯,分别对应4位2进制数的最低位到最高位。如当为0001时路灯亮,当为0011绿灯蓝灯同时亮,然而0001的十进制数是1,0011的十进制数是3,如此这样十进制数从1–>10对应的灯亮,这就是题目要求!
开始编写代码:
led.c中:
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;//定义一个结构体变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//启动PA的时钟
//给结构体的成员变量赋值
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//输出模式
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_6;//同时选中了0和6
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//工作频率
GPIO_Init(GPIOA,&GPIO_InitStruct);//PA0 对PA0进行初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//启动PA的时钟
//给结构体的成员变量赋值
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//输出模式
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_5;//选中了0和5
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//工作频率
GPIO_Init(GPIOB,&GPIO_InitStruct);//PB0 对PA0进行初始化
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}
int main(void)
{
int num;
for(num = 0; num < 16; num++)
{ //真 灯亮 //假 灯灭
//第一个高位黄灯
num & 8 ? GPIO_ResetBits(GPIOA,GPIO_Pin_0) : GPIO_SetBits(GPIOA,GPIO_Pin_0);
//第二个 红灯
num & 4 ? GPIO_ResetBits(GPIOA,GPIO_Pin_6) : GPIO_SetBits(GPIOA,GPIO_Pin_6);
//第三个 蓝灯
num & 2 ? GPIO_ResetBits(GPIOB,GPIO_Pin_0) : GPIO_SetBits(GPIOB,GPIO_Pin_0);
//第四个 绿灯
num & 1 ? GPIO_ResetBits(GPIOB,GPIO_Pin_5) : GPIO_SetBits(GPIOB,GPIO_Pin_5);
}
}
开始代码的编写:
同样接入了按键,也需要对按键进行初始化,不同于LED的是,按键直接在main.c中初始化即可。
void keyInit()
{
GPIO_InitTypeDef GPIO_InitStruct;//定义一个结构体变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//启动PC的时钟
//给结构体的成员变量赋值
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;//输入模式
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1 | GPIO_Pin_7;//选中了1和7引脚
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//工作频率
GPIO_Init(GPIOC,&GPIO_InitStruct);//PA0 对PA0进行初始化
}
int main(void)
{
keyInit();//按键初始化
LED_GPIO_Config();//LED初始化
while(1)
{
//读取按键
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1) == 0)//KEY1
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//LED黄灯亮
}
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_7) == 0)//KEY2
{
GPIO_SetBits(GPIOA,GPIO_Pin_0);//LED黄灯灭
}
}
return 0;
}
答:用flag状态标志位
代码如下:
int main(void)
{
int flag = 1;//相当于标志位
keyInit();//按键初始化
LED_GPIO_Config();//LED初始化
while(1)
{
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1) == 0)//按了key1
{
if(flag)//第一次点按键,flag==1,条件成立
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
flag = 0;
}
else
{
GPIO_SetBits(GPIOA,GPIO_Pin_0);
flag = 1;
}
}
main_delay(200);//按键消抖
}
return 0;
}