查看: 1230|回复: 0
打印 上一主题 下一主题

PIC32MZ之I/O控制

[复制链接]
跳转到指定楼层
沙发
发表于 2015-6-14 16:37:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人现在接触PIC32MZ入门开发套件有一段时间了,现在我分享开发经验吧。
开发套件:PIC32MZ入门套件 开发的软件平台:MPLAB X IDE, MPLAB XC32
    I /O控制对于单片机而言是最基础最核心的东西,其实单片机除了AD DA 转换之外的事情。其他大部分的事情I /O
口都能做的到。I /O控制简单却能千变万化。
单片机在大部分应用中做的事情,莫过于输入高低电平 ,输出高低电平。就是通过这简单的控制电平来实现大多
数的应用控制。
什么是I/O口?
什么是I /O  就是 I N /OU T 就是 输入/输出。
I/O具体能做什么呢?
如果你是刚刚步入电子的新手,那你最好要知道一下I /O口具体能做什么。感性的认识对你的学习是很有帮助
的。I /O口输出一个高(低)电平可以用来点亮一个LED灯,可以接通过一个继电器,来开启电机,来开启音响。
开启许多的东西,也可以用于通信等等。输入一个高(低)电平可以用来检测按键,检测红外线输入 ,检测信
号,等等。
首先介绍下寄存器,一共有6个寄存器分别是:
1、TRIS 寄存器: 设置数字引脚输入还是输出;置1配置输入(默认);清0配置输出,和51相反。 当想要读取IO的状态是TRIS要配置成1,也就是输入状态,然后用PORT寄存器读。
2. PORTx 端口寄存器   写:实际写入LATx中, 读:读取的是端口引脚信号
3.LATx 端口所存寄存器  写:写入LATx中,  读:读取的是端口锁存器数据
4、CLR 寄存器:清0
5、SET 寄存器:置1
6、INV 寄存器:翻转
    PORTx和LATx在写方面是没有区别的,写PORTx本质是将数据写入LATx,然后更新相应的IO端口。但是读方面有区别,区别在于读PORTx读取的是端口引脚的信号,是同步的。而读取LATx则是读取端口锁存器(LATx)的数据,也就是之前写入PORTx或者LATx的数据。这个应该可以解答PORTx和LATx的区别
    复位后(这里说的是上电和器件复位),默认的是输入状态。没有与模拟输入复用的引脚默认为数字输入状态,与模拟输入复用的引脚默认为模拟输入状态。这点要分清楚啰,如果直接配置寄存器开发的话,这一点还是挺重要的。
    关于CN,主要有三个寄存器。我感觉CN主要作用是用于中断,因为CN的作用本来就是检测IO引脚的电平是否发生改变。因为这个功能,在不同器件工作模式之间切换是十分有帮助的。比如:本来MCU工作在从SLEEP或者IDLE模式(休眠或者空闲),当按下一个按钮时,就切换到正常工作状态,这是不是很像MP4里面待机后恢复呢?CN一共有22个,对应不同的通用IO引脚,太强大了。
    CN一共有三个寄存器,分别是CNCON,CNEN,CNPUE,如果大家的项目中有需要检测IO口电平变化来引发中断处理的,可以查看相关的manual reference的详细介绍。关于CN在不同工作模式下的使用,关于这方面的内容,我以后会出相关的教程。
    PIC32还提供了一项非常强大的功能,也就是“原子级”对基址寄存器操作。听起来有点抽象啊,听我慢慢道来。实际上,上面所讲的所有寄存器都可以加一个功能,也就是X+CLR/SET/INV的功能。神马意思呢?举个例子:
如果我们在用一般的单片机时,比如要对PORTC端口的Bit0位置1(原来都是0),大家可能用:
PORTC | = 0x0001
但是在PIC32中提供了另外一种方法,也就是:
PORTCSET=0x0001
这两个有神马区别呢?其实区别不大,所达到的效果都是一样的。但是后者更快!因为是硬件直接完成!两者皆可,但推荐第二种,还有一个原因,就是更加的稳定。
在“原子级”对基址寄存器操作基础上,它们之间的组合就能操作I/O端口,比如:
TRIS HCSET |= (1<<0);//PORTC寄存器bit0置1
TRIS HCLR |= (1<<0);//PORTC寄存器bit0清0
TRIS HINV |= (1<<0);// PORTC寄存器bit0翻转
首先看开发板,LED部分的电路,引脚连接分别为:
LED1对应PORTH.0
LED2对应PORTH.1
LED3对应PORTH.2
具体的原理图如下:

如果想使LED1亮,只需使PORTB.10置1,操作寄存器也就是:
LATBSET |= (1<<10);//置1
为了能使的语句直观,和51一样能,LED1_ON();操作点亮,通俗易懂,我使用#define自定义。
下面我就基于寄存器来点亮板上的三个灯,代码如下:
#include "xc.h"
/* SYSCLK = 200 MHz(8MHz Crystal / FPLLIDIV * FPLLMUL / FPLLODIV) */
#pragma configFPLLIDIV = DIV_1, FPLLMULT = MUL_50, FPLLODIV = DIV_2
#pragma configFPLLRNG = RANGE_5_10_MHZ, FPLLICLK = PLL_FRC, FNOSC = SPLL
#pragma configFSOSCEN = OFF, IESO = ON, POSCMOD = OFF, FCKSM = CSECMD
#pragma configFDMTEN = OFF, DMTCNT = DMT31, FWDTEN = OFF, ICESEL = ICS_PGx2
#define SYS_CLK_FREQUENCY
#define LED1_ON() LATHSET = (1<<0)  // LATHSET的bit0位置一
#define LED2_ON() LATHSET = (1<<1)  // LATHSET的bit1位置一
#define LED3_ON() LATHSET = (1<<2)  // LATHSET的bit2位置一
int main (void )
{
SYS_DEVCON_PerformanceConfig(SYS_CLK_FREQUENCY);//设置系统时钟的频率为200M
    TRISHCLR |= (1 << 0)|(1 << 2)|(1<< 1);// //设置端口输出
    PORTHCLR |= (1 << 0)|(1 <<2)|(1 << 1);// 输出0
    while(1)
    {
       LED2_ON();
       LED3_ON();
       LED1_ON();
    }
}
把上面这段代码直接复制到某个例程即可。

实验效果如下图:

接下来我用MPLAB Harmonyv0_80_01b的库函数来写点亮板上3个LED的程序
/* SYSCLK = 200 MHz(8MHz Crystal / FPLLIDIV * FPLLMUL / FPLLODIV) */
#pragma configFPLLIDIV = DIV_1, FPLLMULT = MUL_50, FPLLODIV = DIV_2
#pragma configFPLLRNG = RANGE_5_10_MHZ, FPLLICLK = PLL_FRC, FNOSC = SPLL
#pragma configFSOSCEN = OFF, IESO = ON, POSCMOD = OFF, FCKSM = CSECMD
#pragma config FDMTEN= OFF, DMTCNT = DMT31, FWDTEN = OFF, ICESEL = ICS_PGx2
#defineSYS_CLK_FREQUENCY                      (200000000ul)//设置时钟频率为200M
int main()
{
SYS_DEVCON_PerformanceConfig(SYS_CLK_FREQUENCY);//设置系统时钟的频率为200M
PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0,PORT_CHANNEL_H, PORTS_BIT_POS_0 );//设置PORTH0为输出方式
PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0,PORT_CHANNEL_H, PORTS_BIT_POS_0 ); //设置PORTH1为输出方式
PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0,PORT_CHANNEL_H, PORTS_BIT_POS_0 ); //设置PORTH2为输出方式
PLIB_PORTS_PinClear( PORTS_ID_0, PORT_CHANNEL_H, PORTS_BIT_POS_0);
//清除PORTH0的状态
PLIB_PORTS_PinClear( PORTS_ID_0, PORT_CHANNEL_H, PORTS_BIT_POS_1);
//清除PORTH1的状态
PLIB_PORTS_PinClear( PORTS_ID_0, PORT_CHANNEL_H, PORTS_BIT_POS_2);
//清除PORTH2的状态
while(1)
{
PLIB_PORTS_PinWrite ( PORTS_ID_0 , PORT_CHANNEL_H , PORTS_BIT_POS_0,1);
//PORTH0写1
PLIB_PORTS_PinWrite ( PORTS_ID_0 , PORT_CHANNEL_H , PORTS_BIT_POS_1,1);
//PORTH0写1
PLIB_PORTS_PinWrite ( PORTS_ID_0 , PORT_CHANNEL_H , PORTS_BIT_POS_2,1);
//PORTH0写1
}
}
/* SYSCLK = 200 MHz(8MHz Crystal / FPLLIDIV * FPLLMUL / FPLLODIV) */
#pragma configFPLLIDIV = DIV_1, FPLLMULT = MUL_50, FPLLODIV = DIV_2
#pragma configFPLLRNG = RANGE_5_10_MHZ, FPLLICLK = PLL_FRC, FNOSC = SPLL
#pragma configFSOSCEN = OFF, IESO = ON, POSCMOD = OFF, FCKSM = CSECMD
#pragma configFDMTEN = OFF, DMTCNT = DMT31, FWDTEN = OFF, ICESEL = ICS_PGx2

这段代码是配置位的设定,他可以理解为编译器的预处理吧,位配置可以设定系统晶振的来源,主系统的频率,外设时钟频,关门狗的相关设置等等。

那么在MPLAB X IDE打开位配置的方法如下:


可以看到位配置的参数挺多的,功能很强大。配合PIC32MZ新推出的Harmony库。可以大大的减少了开发人员的时间和初学者能快速掌握PIC32MZ。
    MPLAB Harmony框架是第一款把许可、转售及支持Microchip和第三方中间件、驱动程序、函数库和实时操作系统集成于一体的产品,简化了包括全新PIC32MZ系列在内的所有32位MCU的开发过程,缩短了集成和上市所需的时间;供了一个模块化架构和一个独立于实时操作系统的环境,提高了重复使用率;MPLAB Harmony还提供了一个将经过Microchip测试、调试和可互操作的代码集于一体的抽象而灵活的统一代码源,进一步降低了成本。此外,Harmony框架让代码移植并在Microchip所有32位PIC32单片机之间迁移更为简单,而且,利用这一集成Microchip和第三方代码的源,大大提高了对瞬息万变的终端市场需求的反应速度。

    引用Microchip MCU32部门总监Rod Drake所说的:“MPLAB Harmony开发框架是一款软件开发方法在嵌入式行业无人能及的强大的新工具,可以帮助工程师应对最新设计挑战。显然,目前还没有任何一家其他厂商提供一个全面的统一固件开发框架,让设计人员能够下载并感受其能支持如此广泛的预测试、可互操作软件。”
转载

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表