GPIO | 红外探测
GPIO | 红外探测
小车的循迹功能就是通过4路红外探测黑线来实现的
GPIO 简介
GPIO就是从STM32芯片上引出的引脚,可以通过拉高/拉低电平等方式简单粗暴地控制,也可以使用TIM、UART等系统资源控制,也可以检测GPIO端口电平的高低来实现数据输入。
GPIO输出–以点亮LED为例
编程顺序
- 使能GPIO端口时钟
- 初始化GPIO引脚
- 控制GPIO输出高、低电平
代码分析
1.在.h文件中列出需要的GPIO的宏
编程时使用宏定义便于提高程序的可移植性
每个.h文件都include这个头文件
#include "stm32f10x.h"
1 2 3 4 5 6 7 8
| #define LED1_GPIO_PORT GPIOC #define LED1_GPIO_CLK RCC_APB2Periph_GPIOC #define LED1_GPIO_PIN GPIO_Pin_2
#define LED2_GPIO_PORT GPIOC #define LED2_GPIO_CLK RCC_APB2Periph_GPIOC #define LED2_GPIO_PIN GPIO_Pin_3
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
#define LED1(a) if (a) \ GPIO_SetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);\ else \ GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED2(a) if (a) \ GPIO_SetBits(LED2_GPIO_PORT,LED2_GPIO_PIN);\ else \ GPIO_ResetBits(LED2_GPIO_PORT,LED2_GPIO_PIN)
#define digitalHi(p,i) {p->BSRR=i;} #define digitalLo(p,i) {p->BRR=i;} #define digitalToggle(p,i) {p->ODR ^=i;}
#define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_GPIO_PIN) #define LED1_HI digitalHi(LED1_GPIO_PORT,LED1_GPIO_PIN) #define LED1_LO digitalLo(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED2_TOGGLE digitalToggle(LED2_GPIO_PORT,LED2_GPIO_PIN) #define LED2_HI digitalHi(LED2_GPIO_PORT,LED2_GPIO_PIN) #define LED2_LO digitalLo(LED2_GPIO_PORT,LED2_GPIO_PIN)
|
2.在.c文件中编写GPIO初始化函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| void LED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( LED1_GPIO_CLK | LED2_GPIO_CLK , ENABLE); GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;
GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN); }
|
这个初始化函数是利用库文件写的,首先要打开GPIO端口的时钟,然后向GPIO_InitTypeDef结构体里填入想要配置的相关信息,最后用GPIO_Init()完成配置
3.GPIO端口的8种工作模式
1、4种输入模式
(1)GPIO_Mode_IN_FLOATING 浮空输入
(2)GPIO_Mode_IPU 上拉输入
(3)GPIO_Mode_IPD 下拉输入
(4)GPIO_Mode_AIN 模拟输入
2、4种输出模式
(5)GPIO_Mode_Out_OD 开漏输出(带上拉或者下拉)
(6)GPIO_Mode_AF_OD 复用开漏输出(带上拉或者下拉)
(7)GPIO_Mode_Out_PP 推挽输出(带上拉或者下拉)
(8)GPIO_Mode_AF_PP 复用推挽输出(带上拉或者下拉)
最常用的就是前三种输入模式(根据外设实际情况而定),和复用推挽输出,速度多选50MHZ和10MHZ
GPIO输入 以红外探测为例
红外探测器的使用方
小车的循迹功能就是通过4路红外探测黑线来实现的
GPIO 简介
GPIO就是从STM32芯片上引出的引脚,可以通过拉高/拉低电平等方式简单粗暴地控制,也可以使用TIM、UART等系统资源控制,也可以检测GPIO端口电平的高低来实现数据输入。
GPIO输出–以点亮LED为例
编程顺序
- 使能GPIO端口时钟
- 初始化GPIO引脚
- 控制GPIO输出高、低电平
代码分析
1.在.h文件中列出需要的GPIO的宏
编程时使用宏定义便于提高程序的可移植性
每个.h文件都include这个头文件
#include "stm32f10x.h"
1 2 3 4 5 6 7 8
| #define LED1_GPIO_PORT GPIOC #define LED1_GPIO_CLK RCC_APB2Periph_GPIOC #define LED1_GPIO_PIN GPIO_Pin_2
#define LED2_GPIO_PORT GPIOC #define LED2_GPIO_CLK RCC_APB2Periph_GPIOC #define LED2_GPIO_PIN GPIO_Pin_3
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
#define LED1(a) if (a) \ GPIO_SetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);\ else \ GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED2(a) if (a) \ GPIO_SetBits(LED2_GPIO_PORT,LED2_GPIO_PIN);\ else \ GPIO_ResetBits(LED2_GPIO_PORT,LED2_GPIO_PIN)
#define digitalHi(p,i) {p->BSRR=i;} #define digitalLo(p,i) {p->BRR=i;} #define digitalToggle(p,i) {p->ODR ^=i;}
#define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_GPIO_PIN) #define LED1_HI digitalHi(LED1_GPIO_PORT,LED1_GPIO_PIN) #define LED1_LO digitalLo(LED1_GPIO_PORT,LED1_GPIO_PIN)
#define LED2_TOGGLE digitalToggle(LED2_GPIO_PORT,LED2_GPIO_PIN) #define LED2_HI digitalHi(LED2_GPIO_PORT,LED2_GPIO_PIN) #define LED2_LO digitalLo(LED2_GPIO_PORT,LED2_GPIO_PIN)
|
2.在.c文件中编写GPIO初始化函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| void LED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( LED1_GPIO_CLK | LED2_GPIO_CLK , ENABLE); GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;
GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN); }
|
这个初始化函数是利用库文件写的,首先要打开GPIO端口的时钟,然后向GPIO_InitTypeDef结构体里填入想要配置的相关信息,最后用GPIO_Init()完成配置
3.GPIO端口的8种工作模式
1、4种输入模式
(1)GPIO_Mode_IN_FLOATING 浮空输入
(2)GPIO_Mode_IPU 上拉输入
(3)GPIO_Mode_IPD 下拉输入
(4)GPIO_Mode_AIN 模拟输入
2、4种输出模式
(5)GPIO_Mode_Out_OD 开漏输出(带上拉或者下拉)
(6)GPIO_Mode_AF_OD 复用开漏输出(带上拉或者下拉)
(7)GPIO_Mode_Out_PP 推挽输出(带上拉或者下拉)
(8)GPIO_Mode_AF_PP 复用推挽输出(带上拉或者下拉)
最常用的就是前三种输入模式(根据外设实际情况而定),和复用推挽输出,速度多选50MHZ和10MHZ
GPIO输入 以红外探测为例
红外传感器使用方法
通过查阅使用说明或者淘宝详情得知,当灵敏度调整正确时,在白色处输出低电平,LED亮;在黑色处输出高电平,LED灭。所以设计程序应该设置GPIO为上拉输入或浮空输入,即当探测到黑线时产生输入。这里我选择上拉输入,因为上拉输入更适合调整输入后产生的动作对应的延迟。
另外使用 GPIO_ReadInputDataBit(GPIOx_PORT,GPIOx_PIN) 来读取上拉输入。
XUNJI.h 里面的定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
#define XUNJI1_GPIO_CLK RCC_APB2Periph_GPIOA #define XUNJI1_GPIO_PORT GPIOA #define XUNJI1_GPIO_PIN GPIO_Pin_12
#define XUNJI2_GPIO_CLK RCC_APB2Periph_GPIOA #define XUNJI2_GPIO_PORT GPIOA #define XUNJI2_GPIO_PIN GPIO_Pin_2
#define XUNJI3_GPIO_CLK RCC_APB2Periph_GPIOA #define XUNJI3_GPIO_PORT GPIOA #define XUNJI3_GPIO_PIN GPIO_Pin_4
#define XUNJI4_GPIO_CLK RCC_APB2Periph_GPIOA #define XUNJI4_GPIO_PORT GPIOA #define XUNJI4_GPIO_PIN GPIO_Pin_5
#define XUNJI5_GPIO_CLK RCC_APB2Periph_GPIOC #define XUNJI5_GPIO_PORT GPIOC #define XUNJI5_GPIO_PIN GPIO_Pin_0
#define R1 GPIO_ReadInputDataBit(XUNJI1_GPIO_PORT,XUNJI1_GPIO_PIN) #define R2 GPIO_ReadInputDataBit(XUNJI2_GPIO_PORT,XUNJI2_GPIO_PIN) #define L2 GPIO_ReadInputDataBit(XUNJI3_GPIO_PORT,XUNJI3_GPIO_PIN) #define L1 GPIO_ReadInputDataBit(XUNJI4_GPIO_PORT,XUNJI4_GPIO_PIN)
#define F1 GPIO_ReadInputDataBit(XUNJI5_GPIO_PORT,XUNJI5_GPIO_PIN)
|
配置XUNJI.c,初始化GPIO端口,写读取GPIO输入函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| void xunji_Init() { GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( XUNJI1_GPIO_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = XUNJI1_GPIO_PIN|XUNJI2_GPIO_PIN|XUNJI3_GPIO_PIN|XUNJI4_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(XUNJI1_GPIO_PORT , &GPIO_InitStructure);
RCC_APB2PeriphClockCmd( XUNJI5_GPIO_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = XUNJI5_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(XUNJI5_GPIO_PORT , &GPIO_InitStructure);
}
void Read_xunji_Date(void) { L1; L2; R2; R1; F1; }
|
在 main.c 中,可以用循环和if语句来读取红外传感器的值并作出指令
1 2 3 4 5 6 7 8 9
| while(1) { Read_xunji_Date(); if(L1==0&&L2==1&&R2==1&&R1==0) { Go(); delay_ms(100); } }
|
具体的循迹指令可以参考源文件
但是主要是要理解循迹的逻辑,具体的代码还要根据实际跑道进行优化