GPIO即可编程输入输出口,LK32T102有3组GPIO口,每组最多32条口线。GPIO口线可以实现很多的功能,可以说掌握了GPIO功能也就MCU编程也就基本实现了MCU的入门。
GPIO功能使用
要注意LTK320T的管脚是多功能的,可作为数字量管脚,也可以作为模拟量管脚。
输入模式 | 浮空输入模式 | 输入完全由外部输入决定 | PU,PD都不导通 |
上拉输入模式 | IO悬空时输入为高电平 | PU导通,PD不导通 | |
下拉输入模式 | IO悬空时输入为低电平 | PU不导通,PD导通 | |
模拟输入模式 | 接模拟信号 | 无特殊要求 | |
输出模式 | 开漏输出模式 | ||
开漏复用输出模式 | |||
推挽输出模式 | |||
推挽复用输出模式 |
首先涉及到管脚功能的选择,涉及到多个寄存器,主要涉及:
*清零和置位本质上是通过两个地址来控制物理上的一个寄存器,使得每一位都可以独立修改,而无需担心在两个进程竞争访问过程时出现的数据丢失(?)--<<ARM Cortex-M0权威指南(中文版)>>P127
为简化操作,模板中提供了很多函数及宏,主要声明在gpio.h,函数实现在gpio.c
void GPIO_AF_SEL(uint8_t AD,PA_Type* GPIOx,uint8_t gpiopin,uint8_t fun_num) | 设定管脚功能 | AD: DIGITAL ANALOGY | 数字管脚功能还是模拟管脚功能 | |
GPIOx:PA,PB,PC | 那一组管脚 | |||
gpiopin:0~31 | 管脚号 | |||
fun_num:0~7 | 功能号 | |||
void GPIO_OD_SEL(uint8_t OD,PA_Type* GPIOx,uint8_t gpiopin); void GPIO_DRV_SEL(uint8_t DRV,PA_Type* GPIOx,uint8_t gpiopin); void GPIO_PUPD_SEL(uint8_t PUPD,PA_Type* GPIOx,uint8_t gpiopin); | ||||
void GPIO_Init() | 管脚初始化 | 主函数main中调用了Device_Init();而Device_Init()又调用了GPIO_Init(),此函数我们根据需要修改,主要调用GPIO_AF_SEL | ||
功能 | 直接操作寄存器 | 备注 | ||
输出功能宏 | PA_OUT_ENABLE(x) | 输出使能 | PA -> OUTEN |= (1 << x); | 以PA为例,其他类似,也可以直接操作寄存器 |
PA_OUT_DISABLE(x) | 输出不能 | PA -> OUTEN &= ~(1<<x); | ||
PA_OUT_HIGH(x) | 输出高 | PA -> OUTSET = (1<<x); | ||
PA_OUT_LOW(x) | 输出低 | PA -> OUTCLR = (1<<x); | ||
PA_OUT_TOGGLE(x) | 输出反转 | PA->OUTTGL = (1<<x); | ||
中断功能宏 | PA_INT_ENABLE(x) | 中断使能 | PA->INTMASK&=~(1<<x); | |
PA_INT_DISABLE(x) | 中断屏蔽 | PA->INTMASK|=(1<<x); | ||
PA_INT_LEVEL(x) | 电平触发 | PA->INTTYPE&=~(1<<x); | ||
PA_INT_EDGE(x) | 边沿触发 | PA->INTTYPE|=(1<<x); | ||
PA_INT_BE_ENABLE(x) | 双边沿触发 | PA->INTBV|=(1<<x); | ||
PA_INT_BE_DISABLE(x) | 单边沿触发 | PA->INTBV&=~(1<<x); | ||
PA_INT_POL_HIGH(x) | 上升沿或高电平触发 | PA->INTPOL|=(1<<x); | ||
PA_INT_POL_LOW(x) | 下升沿或低电平触发 | PA->INTPOL&=~(1<<x); | ||
PA_INT_FLAG_CLR(x) | 中断标志清除 | PA->RIS=(1<<x); |
/*
实现PA0输出高电平
*/
GPIO_AF_SEL(DIGITAL,PA,0,0);//设置管脚PA0为数字功能选择,且为GPIO功能
PA_OUT_ENABLE(0);//PA0输出使能
PA_OUT_HIGHT(0);
GPIO口使用步骤:
1.选择管脚,设定管脚功能
GPIO_AF_SEL();
2.设定GPIO输出方向
1).使能GPIO输出
Pn_OUT_ENABLE(x);//(n=A,B,C)
2)使能GPIO输入
Pn_OUT_DISABLE(x);//(n=A,B,C)
3.设定管脚值
1)设定输出高电平
Pn_OUT_HIGH(x);//(n=A,B,C)
2)设定输出低电平
Pn_OUT_LOW(x);//(n=A,B,C)
3)设定高低电平
Pn->OUT=x;//(n=A,B,C)
4.判断管脚值的高低
1)判断x管脚是否为高(n=A,B,C)
(Pn->PIN&(1<<x))!=0
2)判断x管脚是否为低(n=A,B,C)
(Pn->PIN&(1<<x))==0
5.获取管脚值(n=A,B,C x=0~15)
Px->PIN_b.INx
实例
1.流水灯
/*
实现流水灯
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
//流水灯的花型数据
unsigned char table[]={(1<<0),(1<<1),(1<<2),(1<<3),(1<<4),(1<<5),(1<<6),(1<<7),};
int main(void){
int i=0;
//设备初始化
Device_Init();//Device_Init()主要用到其中的管脚功能选择,也可以在GPIO_Init函数中修改
//也可以直接操作寄存器,不用此函数,但是会比较麻烦
PB -> OUTEN |=0x00ff;//直接操作寄存器,使选定的管脚可以输出,亦可以直接用8个宏PA_OUT_ENABLE(x)
while(1){
for(i=0;i<sizeof(table)/sizeof(char);i++){
//熄灭8个LED
PB -> OUTSET=0X00FF;//输出8个高电平,或其他的PA口管脚不受到影响
//亦可以用8个PA_OUT_HIGH(x)
delay_ms(2000);
//点亮8个LED
PB ->OUTCLR =table[i];//输出8个低电平,其他的PA口管脚不受到影响
//亦可以用8个PA_OUT_LOW(x)
delay_ms(2000);
}
}
}
2.板上按键
/*
按下核心板上SB1~SB4,相应的核心板上LED1~LED4点亮,释放按键,相应的LED0~LED3熄灭
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
//流水灯的花型数据
unsigned char table[]={(1<<0),(1<<1),(1<<2),(1<<3),(1<<4),(1<<5),(1<<6),(1<<7),};
int main(void){
int i=0;
//设备初始化
Device_Init();//Device_Init()主要用到其中的管脚功能选择,也可以在GPIO_Init函数中修改
//也可以直接操作寄存器,不用此函数,但是会比较麻烦
PB -> OUTEN |=0x00ff;//直接操作寄存器,使选定的管脚可以输出,亦可以直接用8个宏PA_OUT_ENABLE(x)
while(1){
if((PA->PIN&(1<<0))==0){//SB1按下
PB->OUTCLR=1<<0;//点亮灯LED1
}else{
PB->OUTSET=1<<0;//熄灭灯LED1
}
if((PA->PIN&(1<<1))==0){//SB2按下
PB->OUTCLR=1<<1;//点亮灯LED2
}else{
PB->OUTSET=1<<1;//熄灭灯LED2
}
if((PA->PIN&(1<<10))==0){//SB3按下
PB->OUTCLR=1<<10;//点亮灯LED3
}else{
PB->OUTSET=1<<10;//熄灭灯LED3
}
if((PA->PIN&(1<<11))==0){//SB4按下
PB->OUTCLR=1<<11;//点亮灯LED4
}else{
PB->OUTSET=1<<11;//熄灭灯LED4
}
}
}
注意在提供的例程其keyboard4x4.c中实现了核心板的键功能,疑似有问题,不要使用,如需使用核心板上的按键请按上述代码实现。
3.扩展板操作的矩阵式按键
扩展板是一个4X4的矩阵式按键。
矩阵式按键可以操作更多按键,其实质也是GPIO口的操作。
对于提供的模板来说,已经实现了操作代码,其以PB口来实现,如果需要改变接线需要修改keyboard4x4.c的uint8_t scan_MatrixKey( void ),并修改gpio.c中的GPIO_Init()中的有关配置,设置相应的管脚为GPIO口。示例中其在GPIO_Init中已经进行了配置,在keyboard4x4.c中实现了功能,一般可以直接调用。
scan_MatrixKey用行反转法识别按键。
/*
按下扩展板上按键,相应的核心板上LED点亮或蜂鸣器响
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
/**
* @param SC32F5832 -> KeyBoard
* PB8 -> CN3-R1
* PB9 -> CN3-R2
* PB10 -> CN3-R3
* PB11 -> CN3-R4
* PB12 -> CN3-C1
* PB13 -> CN3-C2
* PB14 -> CN3-C3
* PB15 -> CN3-C4
*/
/*#define---------------------------------------------------------------------*/
#define BUZZER_OFF PA -> OUTSET = (1 << 12) //蜂鸣器响
#define BUZZER_ON PA -> OUTCLR = (1 << 12) //蜂鸣器关断
#define LED1_ON PB -> OUTCLR = (1 << 0)//PB0 -D9 输出低电平,LED1亮
#define LED2_ON PB -> OUTCLR = (1 << 1)//PB0 -D10 输出低电平,LED2亮
#define LED3_ON PB -> OUTCLR = (1 << 2)//PB0 -D11 输出低电平,LED3亮
#define LED4_ON PB -> OUTCLR = (1 << 3)//PB0 -D12 输出低电平,LED4亮
#define LED5_ON PB -> OUTCLR = (1 << 4)//PB0 -D14 输出低电平,LED5亮
#define LED6_ON PB -> OUTCLR = (1 << 5)//PB0 -D15 输出低电平,LED6亮
#define LED7_ON PB -> OUTCLR = (1 << 6)//PB0 -D16 输出低电平,LED7亮
#define LED8_ON PB -> OUTCLR = (1 << 7)//PB0 -D17 输出低电平,LED8亮
#define LED1_OFF PB -> OUTSET = (1 << 0)//PB0 -D9 输出高电平,LED1灭
#define LED2_OFF PB -> OUTSET = (1 << 1)//PB0 -D10 输出高电平,LED2灭
#define LED3_OFF PB -> OUTSET = (1 << 2)//PB0 -D11 输出高电平,LED3灭
#define LED4_OFF PB -> OUTSET = (1 << 3)//PB0 -D12 输出高电平,LED4灭
#define LED5_OFF PB -> OUTSET = (1 << 4)//PB0 -D14 输出高电平,LED5灭
#define LED6_OFF PB -> OUTSET = (1 << 5)//PB0 -D15 输出高电平,LED6灭
#define LED7_OFF PB -> OUTSET = (1 << 6)//PB0 -D16 输出高电平,LED7灭
#define LED8_OFF PB -> OUTSET = (1 << 7)//PB0 -D17 输出高电平,LED8灭
int main()
{
Device_Init();
PB -> OUTEN |= 0xff;//PB0~PB7,输出,控制LED
//PB8~PB15,一半输入,一半输出,控制矩阵式按键
PB -> OUT |= 0xffff;//PB0~PB15全输出高电平
PA_OUT_ENABLE(12); //核心板蜂鸣器管脚使能
BUZZER_OFF; //蜂鸣器关断
while(1)
{
i = scan_MatrixKey();//读取矩阵式按键键值
if(1 == i) //按键1按下
LED1_ON;//LED1亮
else
LED1_OFF;
if(5 == i) //按键5按下
LED2_ON;//LED2亮
else
LED2_OFF;
if(9 == i ) //按键9按下
LED3_ON;//LED3亮
else
LED3_OFF;
if(13 == i ) //按键13按下
BUZZER_ON;//蜂鸣器响
else
BUZZER_OFF;//蜂鸣器关断
}
}
4扩展板的LCD液晶显示屏操作:
扩展板上的LCD12864是带中文字库的128X64点阵图形液晶显示模块,可以显示8×4 行16×16 点 阵的汉字。
其实质也是GPIO操作,其用GPIO口模拟实现液晶电路的接口操作。
对于提供的模板来说,已经实现了操作代码,其以PC口来实现。如果需要改变接线,修改的内容较多,一般可以直接调用。
/*
LCD显示实验
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
#define BUZZER_OFF PA -> OUTSET = (1 << 12) //蜂鸣器响
#define BUZZER_ON PA -> OUTCLR = (1 << 12) //蜂鸣器关断
/**
* @brief LCD12864接线
* @param SC32F5832 -> LCD12864
* PC6 -> CN3-RS
* PC4 -> CN3-RW
* PC3 -> CN3-E
* PC7 -> CN3-PSB
* PC15 -> CN3-RST
*/
int main( void )
{
Device_Init();
//LCD12864============================
delay_ms(500);
LCD_GPIO_Init();//LCD12864 GPIO初始化
PSB_0;
CS_1;
lcd_init();//LCD12864初始化
delay_ms(100);
lcd_clear();//清屏
delay_ms(100);
lcd_wstr(2, 0, "例程");//
lcd_wstr(2,7,"15℃");
write_figer(2,5,1234);
BUZZER_OFF;
//LCD12864============================
while(1);
}
上述的例程可以直接套用,在需要显示的时候可以直接调用,我们主要涉及到void lcd_wstr(uint8_t y_add , uint8_t x_add , char *str) 和void write_figer(uint8_t y_add, uint8_t x_add, uint32_t figer)
lcd_wstr实现了在y_add行,x_add位置开始写了1个字符串str,而write_figer实现了在y_add行,x_add位置开始写了1个特殊格式的浮点数.。建议直接使用sprintf函数将浮点数变为字符串
#include“stdio.h”
int main(){
float f=3.1415;
char buff[10];
sprintf(buff,"%f",f)
printf("the result=%s",buff);
return 1;
}
示例中似乎有瑕疵
5.扩展板的数码管
温度测量扩展板上的数码管是GPIO应用的一个例子。
/*
温度扩展板上数码管显示1234
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
/** @brief:温度测量扩展板的接线说明
* PB8 -> pa
* PB9 -> pb
* PB10 -> pc
* PB11 -> pd
* PB12 -> pe
* PB13 -> pf
* PB14 -> pg
* PB15 -> dp
*
* PA4 -> 74LS138-A0
* PA5 -> 74LS138-A1
* PA6 -> 74LS138-A2
*
*/
int main( void )
{
Device_Init();
SEG_GPIO_Init();
while(1){
Dispaly_Number( 0, 1 );
ST_delay_ms( 2 );
Dispaly_Number( 1, 2 );
ST_delay_ms( 2 );
Dispaly_Number( 2, 3 );
ST_delay_ms( 2 );
Dispaly_Number( 3, 4 );
ST_delay_ms( 2 );
Dispaly_Number( 10, 3 );
}
}
在利用模块的时候发现有问题,
6.扩展板的DS18B20
温度测量扩展板上的DS18B20是一种单总线的数字式测温传感器,MCU只需要一个GPIO口线就可以和其通信,对其进行控制。下面的实验将测量的温度显示在lcd上
/*
LCD显示实验
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
#define BUZZER_OFF PA -> OUTSET = (1 << 12) //蜂鸣器响
#define BUZZER_ON PA -> OUTCLR = (1 << 12) //蜂鸣器关断
/**
* @brief LCD12864接线说明
* @param SC32F5832 -> LCD12864
* PC6 -> CN3-RS
* PC4 -> CN3-RW
* PC3 -> CN3-E
* PC7 -> CN3-PSB
* PC15 -> CN3-RST
*/
/**
* @brief 单总线温度传感器接线说明
* @param SC32F5832 -> 温度传感器模块
* PA15 -> CN2-DSO
*/
int main( void )
{
Device_Init();
PA_OUT_ENABLE(12);//蜂鸣器使能
//LCD12864============================
delay_ms(500);
LCD_GPIO_Init();//LCD12864 GPIO初始化
PSB_0;
CS_1;
lcd_init();//LCD12864初始化
delay_ms(100);
lcd_clear();//清屏
delay_ms(100);
lcd_wstr(2, 0, "例程");//
lcd_wstr(2,7,"15℃");
BUZZER_OFF;
while(1){
//工作显示
LED1_ON;
ST_delay_ms(500);
LED1_OFF;
ST_delay_ms(500);
//DS18B20 温度采集
DS18B20_Temp = DS18B20_Get_Temp();
//LCD 数据显示
write_figer(2,4,DS18B20_Temp);
}
}
ps:
学会了这部分内容已经完成大部分任务了,下面就是中断、定时计数器、AD及PWM
/***********************************************************************************************************/
很遗憾,有很多的东西我没有办法一一给大家回复,所以我建立了一个群,供大家一起交流!