【MM32 MiniBoard试用体验】果爸的MM32之路——GPIO篇
首先,在元旦前夕这个时候祝愿大家节日快乐。自从果果出生以来,想要静下心来学习一下的时间真是越来越少了,每天睡眠严重不足,每天围着各种尿布转,有了宝宝之后生活质量一下大变样,有宝宝的同学你们懂的。还好果果妈对我学习还比较支持,让我在稍微闲暇的时间能够看看书,做做实验,充充电。对果果妈的支持理解表示万分感谢。
言归正传,由于之前只有51的基础,水平低的不能再低了,对ARM处理器不慎了解,所以只能从点滴学起。结合之前学51的经验,我感觉理论和实验结合着学是最快捷的途径,由浅入深是学习事半功倍的不破真理,玩一些能看的到的简单实验,从玩开始学,才能越学越有兴趣,否则直接看一些复杂的资料,只会把看蒙圈。所以我准备按照GPIO、定时器、中断、uart及端口复用、A/D、比较捕捉与PWM、PCI与I2C等常用设备接口、常用工业总线与接口、软件设计这个步骤来进行。那么这次我就从GPIO先开始。
之所以选择GPIO,是因为外接的设备都是需要GPIO的(这是一句废话),也只有连了外部设备,各种实验效果才最明显。要学习一个设备,第一件事就是学习它的技术手册啦,所以我翻出了已经在电脑里趴了好几天的用户手册和产品手册。
MM32F031的通用输入输出接口(GPIO)配置成输出(推挽或开漏)、输入(带或不带上拉或下拉)或复用的外设功能端口。多数GPIO引脚都与数字或模拟的复用外设共用。除了具有模拟输入功能的端口,所有的GPIO引脚都有大电流通过能力。(这里看来产品手册上写的是25mA)。其中包扣16位的PA、PB,PC13-15,PD0-3,其中PD0、PD1作为OSC_IN,OSC_OUT。
每个 GPIO 端口有两个 32 位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个 32 位数据寄存器(GPIOx_IDR 和GPIOx_ODR),一个 32 位置位/复位寄存器(GPIOx_BSRR),一个 16 位复位寄存器(GPIOx_BRR)、一个 32 位锁定寄存器(GPIOx_LCKR)和两个复用功能选择寄存器(GPIOx_AFRH)
和(GPIOx_AFRL).
配置寄存器(GPIOx_CRL,GPIOx_CRH)分别配置GPIO端口的第八位和高八位,分别由CNFy[1 :0]、 MODEy[1 :0]设置端口配置和端口模式,其中MODEy[1 :0]==00时位输入模式,>00时位输出模式,最大输出频率50MHz,当端口处于输入模式时,CNFy[1 :0]的值分别代表00:模拟输入模式,01:浮空输入模式,10:上拉/下拉输入模式,11:保留;当端口处于输出模式时,00:通用推挽输出模式,01:通用开漏输出模式,10:复用功能推挽输出模式,11:复用功能开漏输出模式。
复用功能选择寄存器(GPIOx_AFRH)和(GPIOx_AFRL),分别配置端口的高八位和低八位的管脚复用,AFRy[3:0] 数值0000:AF0,0001:AF1,0010:AF2,0011:AF3,0100:AF4,0101:AF5。各个复用具体信息详见产品手册表4表5。
看了这些资料感到mm32在GPIO上和51并无太多区别,只是其复用较多,需要进一步学习罢了。理论再多不如学以致用,实践是检验真理的唯一标准,只有实验才能看到学习的效果,在做实验之前,要进一步了解mini开发板,翻出SCH文件,发现PA、PB很多都是复用接出,PA11、12、15,PB3、4、5分别接在了USB与LED上,PB0、1闲置未引出外,其他管脚均能单独接出。
正好手头有现成的数码管板子,用245和138芯片做段位选择, PA[0:1,4:8,13]接245段选,PB接138位选[4:6]。参考代码如下:
#include"delay.h"
#include"sys.h"
#include"led.h"
#define GPIO_DIGGPIOA
uint16_tDIG_CODE[17]={
0x00f3,0x0012,0x0163,0x0133,0x0192,0x01b1,0x01f1,0x0013,
0x007f,0x006f,0x0077,0x007c,0x0039,0x005e,0x0079,0x0071};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码
uint16_tDisplayData[8];
//用来存放要显示的8位数的值
void DigDisplay()
{
unsigned char i;
unsigned int j;
for(i=0;i<8;i++)
{
switch(i) //位选,选择点亮的数码管,
{
case(0):
GPIO_Write(GPIOB,0x0000); break;//显示第0位
case(1):
GPIO_Write(GPIOB,0x0010); break;//显示第1位
case(2):
GPIO_Write(GPIOB,0x0020); break;//显示第2位
case(3):
GPIO_Write(GPIOB,0x0030); break;//显示第3位
case(4):
GPIO_Write(GPIOB,0x0040); break;//显示第4位
case(5):
GPIO_Write(GPIOB,0x0050); break;//显示第5位
case(6):
GPIO_Write(GPIOB,0x0060); break;//显示第6位
case(7):
GPIO_Write(GPIOB,0x0070); break;//显示第7位
}
GPIO_Write(GPIOA,DIG_CODE);//发送段码
j=5; //扫描间隔时间设定
while(j--);
GPIO_Write(GPIOA,0x00);//消隐
}
}
uint16_t i;
/********************************************************************************************************
**函数信息 :main(void)
**功能描述 :
**输入参数 :无
**输出参数 :无
********************************************************************************************************/
intmain(void)
{
delay_init();
LED_Init();
//GPIO_DeInit(GPIOB);
//GPIO_DeInit(GPIOA);
//while(1) //无限循环
// {
//LED1_TOGGLE();
// LED2_TOGGLE();
// LED3_TOGGLE();
// LED4_TOGGLE();
//delay_ms(1000);
for(i=0;i<8;i++)
{
DisplayData=DIG_CODE;
}
while(1)
{
DigDisplay();
}
}
//}
/********************************************************************************************************
**函数信息 :LED_Init(void)
**功能描述 :LED初始化
**输入参数 :无
**输出参数 :无
********************************************************************************************************/
voidLED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE); //开启GPIOA,GPIOB时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//GPIO_InitStructure.GPIO_Pin =GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;
//GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
//GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
LED1_OFF();
LED2_OFF();
LED3_OFF();
LED4_OFF();
}
|