码迷,mamicode.com
首页 > 其他好文 > 详细

智能车学习(十四)——K60单片机GPIO学习

时间:2015-11-24 22:53:07      阅读:458      评论:0      收藏:0      [点我收藏+]

标签:

一、头文件:

#ifndef __GPIO_H__
#define __GPIO_H__

#include "gpio_cfg.h"
#include "common.h"

//端口宏定义
typedef enum PORTx
{
    PORTA,
    PORTB,
    PORTC,
    PORTD,
    PORTE
} PORTx;


//定义管脚状态
typedef enum GPIO_CFG
{
    //这里的值不能改!!!
    GPI         = 0,                          //定义管脚输入方向      GPIOx_PDDRn里,0表示输入,1表示输出
    GPO         = 1,                          //定义管脚输出方向

    GPI_DOWN    = 0x02,                       //输入下拉              PORTx_PCRn需要PE=1,PS=0
    GPI_UP      = 0x03,                       //输入上拉              PORTx_PCRn需要PE=1,PS=1
    GPI_PF      = 0x10,                       //输入,带无源滤波器,滤波范围:10 MHz ~ 30 MHz 。不支持高速接口(>=2MHz)  0b10000           Passive Filter Enable
    GPI_DOWN_PF = GPI_DOWN | GPI_PF ,         //输入下拉,带无源滤波器
    GPI_UP_PF   = GPI_UP   | GPI_PF ,         //输入上拉,带无源滤波器

    GPO_HDS     = 0x41,                        //输出高驱动能力   0b100 0001    High drive strength
    GPO_SSR     = 0x05,                        //输出慢变化率          0b101     Slow slew rate
    GPO_HDS_SSR = GPO_HDS | GPO_SSR,           //输出高驱动能力、慢变化率
} GPIO_CFG;  //最低位为0,肯定是输入;GPI_UP 和 GPI_UP_PF的最低位为1,其他为输出


#define HIGH  1u
#define LOW   0u

//它是被设计用来修饰被不同线程访问和修改的变量。如果不加入volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。
extern volatile  struct GPIO_MemMap *GPIOx[5];
extern volatile struct  PORT_MemMap *PORTX[5];

/****************************外部使用****************************/


void    gpio_init  (PORTx, u8 n, GPIO_CFG, u8 data);  //初始化gpio
void    gpio_set   (PORTx,  u8 n,     u8 data);  //设置引脚状态
void    gpio_turn  (PORTx,  u8 n);    //翻转引脚状态   
u8       gpio_get   (PORTx,  u8 n);    //读取引脚状态                                                          

#define GPIO_SET(PORTx,n,x)          GPIO_SET_##x((PORTx),(n))                                  //设置输出电平x,x为0或1   例如 GPIO_SET(PORTA,1,1)  PA1输出高电平
#define GPIO_TURN(PORTx,n)           (GPIO_PDOR_REG(GPIOx[(PORTx)]) ^=  (1<<(n)))               //翻转输出电平
#define GPIO_Get(PORTx,n)            ((GPIO_PDIR_REG(GPIOx[(PORTx)])>>(n))&0x1)                 //读取引脚输入状态

//GPIO  1位操作
#define GPIO_SET_1bit(PORTx,n,data)   GPIO_PDOR_REG(GPIOx[(PORTx)])=(( GPIO_PDOR_REG(GPIOx[(PORTx)])& ~(0x1<<(n)) )|(((data)&0x01)<<(n)))   //写1位数据(n为最低位引脚号)
#define GPIO_DDR_1bit(PORTx,n,ddr)    GPIO_PDDR_REG(GPIOx[(PORTx)])=(( GPIO_PDDR_REG(GPIOx[(PORTx)])& ~(0x1<<(n)) )|(((ddr)&0x01)<<(n)))    //设置1位输入输出方向(n为最低位引脚号)
#define GPIO_GET_1bit(PORTx,n)        (( GPIO_PDIR_REG(GPIOx[(PORTx)])>>(n) ) & 0x1)                                                        //读1位数据(n为最低位引脚号)

//GPIO  2位操作
#define GPIO_SET_2bit(PORTx,n,data)   GPIO_PDOR_REG(GPIOx[(PORTx)])=(( GPIO_PDOR_REG(GPIOx[(PORTx)])& ~(0x3<<(n)) )|(((data)&0x03)<<(n)))   //写2位数据(n为最低位引脚号)
#define GPIO_DDR_2bit(PORTx,n,ddr)    GPIO_PDDR_REG(GPIOx[(PORTx)])=(( GPIO_PDDR_REG(GPIOx[(PORTx)])& ~(0x3<<(n)) )|(((ddr)&0x03)<<(n)))    //设置2位输入输出方向(n为最低位引脚号)
#define GPIO_GET_2bit(PORTx,n)        (( GPIO_PDIR_REG(GPIOx[(PORTx)])>>(n) ) & 0x3)                                                        //读2位数据(n为最低位引脚号)

//GPIO  4位操作
#define GPIO_SET_4bit(PORTx,n,data)   GPIO_PDOR_REG(GPIOx[(PORTx)])=(( GPIO_PDOR_REG(GPIOx[(PORTx)])& ~(0xf<<(n)) )|(((data)&0x0f)<<(n)))   //写4位数据(n为最低位引脚号)
#define GPIO_DDR_4bit(PORTx,n,ddr)    GPIO_PDDR_REG(GPIOx[(PORTx)])=(( GPIO_PDDR_REG(GPIOx[(PORTx)])& ~(0xf<<(n)) )|(((ddr)&0x0f)<<(n)))    //设置4位输入输出方向(n为最低位引脚号)
#define GPIO_GET_4bit(PORTx,n)        (( GPIO_PDIR_REG(GPIOx[(PORTx)])>>(n) ) & 0xf)                                                        //读4位数据(n为最低位引脚号)

//GPIO  8位操作
#define GPIO_SET_8bit(PORTx,n,data)   GPIO_PDOR_REG(GPIOx[(PORTx)])=(( GPIO_PDOR_REG(GPIOx[(PORTx)])& ~(0xff<<(n)) )|(((data)&0xff)<<(n)))  //写8位数据(n为最低位引脚号)  野火注:先清8位,再填进去
#define GPIO_DDR_8bit(PORTx,n,ddr)    GPIO_PDDR_REG(GPIOx[(PORTx)])=(( GPIO_PDDR_REG(GPIOx[(PORTx)])& ~(0xff<<(n)) )|(((ddr)&0x0ff)<<(n)))  //设置8位输入输出方向(n为最低位引脚号)
#define GPIO_GET_8bit(PORTx,n)        (( GPIO_PDIR_REG(GPIOx[(PORTx)])>>(n) ) & 0xff)                                                       //读8位数据(n为最低位引脚号)

//GPIO  16位操作
#define GPIO_SET_16bit(PORTx,n,data)  GPIO_PDOR_REG(GPIOx[(PORTx)])=(( GPIO_PDOR_REG(GPIOx[(PORTx)])&~(0xffff<<(n)) )|(((data)&0xffff)<<(n)))   //写16位数据(n为最低位引脚号)
#define GPIO_DDR_16bit(PORTx,n,ddr)   GPIO_PDDR_REG(GPIOx[(PORTx)])=(( GPIO_PDDR_REG(GPIOx[(PORTx)])& ~(0xffff<<(n)) )|(((ddr)&0x0ffff)<<(n)))  //设置16位输入输出方向(n为最低位引脚号)
#define GPIO_GET_16bit(PORTx,n)       (( GPIO_PDIR_REG(GPIOx[(PORTx)])>>(n) ) & 0xffff)                                                         //读16位数据(n为最低位引脚号)

//GPIO  32位操作
#define GPIO_SET_32bit(PORTx,data)  GPIO_PDOR_REG(GPIOx[(PORTx)])=(data)                                                                    //写32位数据
#define GPIO_DDR_32bit(PORTx,ddr)   GPIO_PDDR_REG(GPIOx[(PORTx)])=(ddr)                                                                     //设置32位输入输出方向
#define GPIO_GET_32bit(PORTx)       GPIO_PDIR_REG(GPIOx[(PORTx)])                                                                           //读32位数据



/****************************内部使用,用户不需要关心****************************/
#define GPIO_SET_1(PORTx,n)          GPIO_PDOR_REG(GPIOx[(PORTx)]) |=  (1<<(n))      //设置输出为高电平        例如:GPIO_SET_H(PORTA,1)   PA1输出高电平
#define GPIO_SET_0(PORTx,n)          GPIO_PDOR_REG(GPIOx[(PORTx)]) &= ~(1<<(n))      //设置输出为低电平        例如:GPIO_SET_L(PORTA,1)   PA1输出低电平

#endif

PS:1、其中volatile是C用来进行多线程处理的关键字。

 

二、源文件:

#include "common.h"
#include "gpio.h"


volatile struct GPIO_MemMap *GPIOx[5] = {PTA_BASE_PTR, PTB_BASE_PTR, PTC_BASE_PTR, PTD_BASE_PTR, PTE_BASE_PTR};                //定义五个指针数组保存 GPIOx 的地址
volatile struct PORT_MemMap *PORTX[5] = {PORTA_BASE_PTR, PORTB_BASE_PTR, PORTC_BASE_PTR, PORTD_BASE_PTR, PORTE_BASE_PTR};


/*************************************************************************
*  函数名称:gpio_init
*  功能说明:初始化gpio
*  参数说明:PORTx       端口号(PORTA,PORTB,PORTC,PORTD,PORTE)
*            n           端口引脚
*            IO          引脚方向,0=输入,1=输出
*            data        输出初始状态,0=低电平,1=高电平 (对输入无效)
*  函数返回:无
*************************************************************************/
void gpio_init (PORTx portx, u8 n, GPIO_CFG cfg, u8 data)
{
    ASSERT( (n < 32u)  && (data < 2u) );           //使用断言检查输入、电平 是否为1bit

    //选择功能脚 PORTx_PCRx ,每个端口都有个寄存器 PORTx_PCRx
    PORT_PCR_REG(PORTX[portx], n) = (0 | PORT_PCR_MUX(1) | cfg);

    //端口方向控制输入还是输出
    if( ( (cfg & 0x01) == GPI) || (cfg == GPI_UP) ||     (cfg == GPI_UP_PF)      )
        //   最低位为0则输入   ||   输入上拉模式  ||   输入上拉,带无源滤波器
    {
        GPIO_PDDR_REG(GPIOx[portx]) &= ~(1 << n);  //设置端口方向为输入
    }
    else
    {
        GPIO_PDDR_REG(GPIOx[portx]) |= (1 << n);    //设置端口方向为输出
        if(data == 1)//output
        {
            GPIO_SET(portx, n, 1);                  //对端口输出控制,输出为1
        }
        else
        {
            GPIO_SET(portx, n, 0);                  //对端口输出控制,输出为0
        }
    }
}


/*************************************************************************
*  函数名称:gpio_set
*  功能说明:设置引脚状态
*  参数说明:PORTx       端口号(PORTA,PORTB,PORTC,PORTD,PORTE)
*            n           端口引脚
*            data        输出初始状态,0=低电平,1=高电平
*  函数返回:无
*************************************************************************/
void gpio_set (PORTx portx, u8 n, u8 data)
{
    ASSERT( (n < 32u)  && (data < 2u) );           //使用断言检查输入、电平 是否为1bit

    if(data == 1)               //输出
        GPIO_SET(portx, n, 1);  //GPIO_PDOR_REG(PORTx) |= (1<<n);
    else
        GPIO_SET(portx, n, 0);  //GPIO_PDOR_REG(PORTx) &= ~(1<<n);
}


/*************************************************************************
*  函数名称:gpio_turn
*  功能说明:反转引脚状态
*  参数说明:PORTx       端口号(PORTA,PORTB,PORTC,PORTD,PORTE)
*            n           端口引脚
*  函数返回:无
*************************************************************************/



void gpio_turn (PORTx portx, u8 n)
{
    ASSERT( n < 32u );           //使用断言检查引脚号
    GPIO_TURN(portx, n);
}

/*************************************************************************
*  函数名称:gpio_get
*  功能说明:读取引脚输入状态
*  参数说明:PORTx       端口号(PORTA,PORTB,PORTC,PORTD,PORTE)
*            n           端口引脚
*  函数返回:无
*************************************************************************/
u8 gpio_get(PORTx portx, u8 n)          //读取引脚状态
{
    ASSERT( n < 32u );                  //使用断言检查引脚号
    return GPIO_Get(portx, n);
}

 

三、小结:

    主要是学会怎么调用,出现问题的话,检查寄存器的配置(不过一般不需要)。

智能车学习(十四)——K60单片机GPIO学习

标签:

原文地址:http://www.cnblogs.com/BlueMountain-HaggenDazs/p/4993121.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!