通过上篇章节的学习,我们通过查看具体的IO框图总结了三个输出模式和三个输出模式:
通用输入:直接检测IO口的电平状态(如果需要读取外界给IO口的电平状态,就要用通用输入模式。
复用输入:从IO进来的数据信号要经过片上外设(串口控制器),再到核心。IO就要用复用输入模式。
模拟输入:外界的模拟量(电压)通过IO口进入到ADC控制器,ADC控制器转换成数字量(模数转换)
通用输出:核心直接控制IO输出高低电平,就用通用输出模式
复用输出:核心将数据信号发送到片上外设,片上外设再通过IO口传送出去.IO口复用输出模式
模拟输出:通过DAC片上外设进行数模转换,再将模拟数据通过IO口传输出去。
我们这章节具体学习一下IO口的具体应用--点灯。
1.配置点灯初始化,首先得看原理图:我们需要通过查看原理图知道LED灯应该配置在哪个IO口上;
以我手上的STM32F101xx板子为例:原理图显示LED灯配置在GPIOB5和GPIOE5上;
2,其次根据不同的模式选择配置不同的寄存器。
根据经验,六种不同的模式我总结了以下六个配置方案:
通用输入
{
端口模式寄存器
上下拉寄存器
输入数据寄存器
}
通用输出
{
端口模式寄存器
输出类型寄存器
输出速度寄存器
输出数据寄存器
}
复用输入
{
端口模式寄存器
上下拉寄存器
复用功能寄存器
}
复用输出
{
端口模式寄存器
输出类型寄存器
输出速度寄存器
上下拉寄存器
复用功能寄存器
}
模拟模式
{
端口模式寄存器
}
注意:这是通过我们查看IO口的寄存器总结出来的,如果真要学习嵌入式的同学请不要死记硬背!!!不同的芯片有不同的配置方式(虽然大同小异)。
#include "stm32f4xx.h" // Device header
#include "led.h"
/***********************************************
*函数名 :Led_Init
*函数功能 :对LED灯所用IO口初始化配置
*函数参数 :无
*函数返回值:无
*函数描述 :LED1--------PC4
LED2--------PC5
LED3--------PC6
LED4--------PC7
************************************************/
void Led_Init(void)
{
//端口时钟使能---C
RCC->AHB1ENR |= (1<<2);
//端口模式配置---通用输出
GPIOC->MODER &= ~((3<<8) | (3<<10) | (3<<12) | (3<<14)); //清零
GPIOC->MODER |=((1<<8) | (1<<10) | (1<<12) | (1<<14));
//端口输出类型怕配置---推挽
GPIOC->OTYPER &= ~((1<<4) | (1<<5) | (1<<6) | (1<<7));
//端口输出速度-------2M
GPIOC->OSPEEDR &= ~((3<<8) | (3<<10) | (3<<12) | (3<<14));
//上下拉配置---------无
GPIOC->PUPDR &= ~((3<<8) | (3<<10) | (3<<12) | (3<<14));
//输出数据寄存器配置----初始状态关
GPIOC->ODR |= ((1<<4) | (1<<5) | (1<<6) | (1<<7));
}
/***********************************************
*函数名 :Led_All_ON
*函数功能 :所有灯开函数
*函数参数 :无
*函数返回值:无
*函数描述 :
************************************************/
void Led_All_ON(void)
{
LED1_ON;
LED2_ON;
LED3_ON;
LED4_ON;
}
/***********************************************
*函数名 :Led_All_OFF
*函数功能 :所有灯关函数
*函数参数 :无
*函数返回值:无
*函数描述 :
************************************************/
void Led_All_OFF(void)
{
LED1_OFF;
LED2_OFF;
LED3_OFF;
LED4_OFF;
}
/***********************************************
*函数名 :Ledx_ON
*函数功能 :某一个灯亮函数
*函数参数 :u8 n
*函数返回值:无
*函数描述 :
************************************************/
void Ledx_ON(u8 n)
{
switch(n)
{
case 1:LED1_ON;break;
case 2:LED2_ON;break;
case 3:LED3_ON;break;
case 4:LED4_ON;break;
}
}
/***********************************************
*函数名 :Ledx_OFF
*函数功能 :某一个灯关函数
*函数参数 :u8 n
*函数返回值:无
*函数描述 :
************************************************/
void Ledx_OFF(u8 n)
{
switch(n)
{
case 1:LED1_OFF;break;
case 2:LED2_OFF;break;
case 3:LED3_OFF;break;
case 4:LED4_OFF;break;
}
}
/***********************************************
*函数名 :Led_Flash
*函数功能 :流水灯函数
*函数参数 :u8 speed
*函数返回值:无
*函数描述 :
************************************************/
void Led_Flash(u8 speed)
{
static u8 led_n = 1;
static u32 cont = 0;
Ledx_ON(led_n);
cont++;
if(cont >= 50000 * speed)
{
Ledx_OFF(led_n);
cont = 0;
led_n++;
if(led_n>4)
{
led_n = 1;
}
}
}
以上为我个人配置LED时的初始化代码,在.c文件中配置(不同的芯片和开发板有不同的IO,但是根据我们学习的寄存器配置方法稍微修改即可)
#include "stm32f4xx.h"
#ifndef _LED_H
#define _LED_H
//函数声明和宏定义
#define LED1_ON (GPIOC->ODR &= ~(1<<4))
#define LED1_OFF (GPIOC->ODR |= (1<<4))
#define LED1_OVERTURN (GPIOC->ODR ^= (1<<4))
#define LED2_ON (GPIOC->ODR &= ~(1<<5))
#define LED2_OFF (GPIOC->ODR |= (1<<5))
#define LED2_OVERTURN (GPIOC->ODR ^= (1<<5))
#define LED3_ON (GPIOC->ODR &= ~(1<<6))
#define LED3_OFF (GPIOC->ODR |= (1<<6))
#define LED3_OVERTURN (GPIOC->ODR ^= (1<<5))
#define LED4_ON (GPIOC->ODR &= ~(1<<7))
#define LED4_OFF (GPIOC->ODR |= (1<<7))
#define LED4_OVERTURN (GPIOC->ODR ^= (1<<7))
void Led_Init(void);
void Led_All_ON(void);
void Led_All_OFF(void);
void Ledx_ON(u8 n);
void Ledx_OFF(u8 n);
void Led_Flash(u8 speed);
#endif
在.h文件中添加宏定义和函数声明,这样会让你的函数更加直观和简单,也更容易让同事们了解你这段在写什么。
最后!!!!!如果真的想往嵌入式靠拢的同学,请务必注重方法和步骤!!拒绝死记硬背!!看图--配置寄存器--写大致框架--写程序,嵌入式所有的知识都能通过这三步来学习!!这里的代码段仅供你们写完参考是否有遗漏!!!