打印
[MCU]

【MSP430i2xx教程第一讲】怎样使用库函数 & GPIO详解

[复制链接]
楼主: xlhtracy
手机看帖
扫描二维码
随时随地手机跟帖
121
强仔00001 发表于 2015-3-29 14:42
已经出了吧,MSP432,好像有一套

是的,已经出了,还有FR系列,功能很强大的。

使用特权

评论回复
122
yangshoot| | 2015-3-29 20:36 | 只看该作者
楼主能编成PDF便于下载阅读就好了

使用特权

评论回复
123
又一个暑假| | 2015-3-30 09:35 | 只看该作者
学习学习

使用特权

评论回复
124
xlhtracy|  楼主 | 2015-3-30 09:41 | 只看该作者
yangshoot 发表于 2015-3-29 20:36
楼主能编成PDF便于下载阅读就好了

本帖子七楼有完整的教程pdf文档可供下载的。还有其他一些资料  ,可以看看~  https://bbs.21ic.com/forum.php?mo ... 9832&fromuid=789019

使用特权

评论回复
125
wudianjun| | 2015-3-30 13:27 | 只看该作者
库用起来还是很方面的,但是对于小内存的芯片,追求空间的话,还是直接寄存器操作比较好,代码效率高。用库,阅读起来方面,移植也很方面,有问题好查找。各有千秋

使用特权

评论回复
126
jazzyfox| | 2015-3-30 13:56 | 只看该作者
这种GPIO的函数看起来差不多,和arm的也很像

使用特权

评论回复
127
112207301219| | 2015-3-30 20:38 | 只看该作者
必胜客A 发表于 2015-3-24 21:36
1、为什么关于中断边沿选择的函数GPIO_interruptEdgeSelect()的参数selectedPort可以有18个量可以选择,而 ...

这个问题好像没有说到点子上吧,我觉得楼主的意思是为什么除了选择触发沿的函数有18个值可选,其他与中断有关的函数只有3个值可以选,既然如此,选择触发沿的函数传入其他的15个值时有何意义呢?并且手册中只明确说了P1和P2有中断功能,那么问题来了,传入其他15个值时意义何在?有可能是编写库函数时为特殊器件预留的。如果是这样,那么其它与中断有关的函数为什么不预留呢?

使用特权

评论回复
128
112207301219| | 2015-3-30 20:49 | 只看该作者
数码小叶 发表于 2015-3-25 08:32
虽然打了很多字,可是真较真起来,突然觉得这个问题没意义了

应该是编写库函数时疏忽了吧

使用特权

评论回复
129
112207301219| | 2015-3-30 21:12 | 只看该作者
gaoyang9992006 发表于 2015-3-27 18:29
#define GPIO_PORT_P1                                                          1
#define GPIO_PORT_ ...

下面是库函数中GPIO_interruptEdgeSelect函数的实现方法:
请问那句话是判断字寻址和字节寻址的啊?

void GPIO_interruptEdgeSelect(uint8_t selectedPort,
                              uint16_t selectedPins,
                              uint8_t edgeSelect) {
    uint16_t baseAddress = GPIO_PORT_TO_BASE[selectedPort];

    #ifndef NDEBUG
    if(baseAddress == 0xFFFF)
    {
        return;
    }
    #endif

    // Shift by 8 if port is even (upper 8-bits)
    if((selectedPort & 1) ^ 1)
    {
        selectedPins <<= 8;
    }

    if(GPIO_LOW_TO_HIGH_TRANSITION == edgeSelect)
    {
        HWREG16(baseAddress + OFS_PAIES) &= ~selectedPins;
    }
    else
    {
        HWREG16(baseAddress + OFS_PAIES) |= selectedPins;
    }
}

使用特权

评论回复
130
112207301219| | 2015-3-30 21:18 | 只看该作者
feiting94 发表于 2015-3-28 10:02
楼主是这样写的,GPIO_interruptEdgeSelect(),该函数是通过修改寄存器PxIES实现,返回值 None(空)。
如果 ...

我也认为应该只有3个。不过或许是预留的,手册中说有些器件可能其他的端口也有中断功能。但是要预留的话,应该所有与中断有关的的函数都预留才对,总之这里应该是有问题的。

使用特权

评论回复
131
112207301219| | 2015-3-30 21:27 | 只看该作者
awficel1 发表于 2015-3-28 10:19
1答:其他4个关于中断设置的函数,只有P1、P2、PA具有该功能.

那就没必要选择其他端口的触发沿了,因为根本就没有中断功能,也就是说其他15个量传给触发沿选择函数是无效的。

使用特权

评论回复
132
hanzhenfei| | 2015-3-30 21:28 | 只看该作者
作者文中写到:
uint8 t GPIO_getInputPinValue (uint8_t selectedPort, uint16_t selectedPins)
  该函数获取所选管脚的输入值。
     该函数具有两个参数:selectedPort(所选端口)和selectedPins(所选管脚)。
     selectedPort可选的有效值有1811+7)个:GPIO_PORT_P1、GPIO_PORT_P2……GPIO_PORT_P11,GPIO_PORT_PA、         GPIO_PORT_PBGPIO_PORT_PCGPIO_PORT_PD、GPIO_PORT_PE、GPIO_PORT_PF、GPIO_PORT_PJ。
    注意:数字标记的为以字节为操作位宽(8位)的,字母标记的为以字为位宽(16位)操作的。
    selectedPins是所选端口上的管脚。其掩码值可以是GPIO_PIN0GPIO_PIN1、GPIO_PIN2……GPIO_PIN15等十六个值的逻辑或
    返回值:GPIO_INPUT_PIN_HIGHGPIO_INPUT_PIN_LOW二者中之一。即管脚的状态值。

问题:因为返回值是真或否,总感觉selectPin不应该是所选引脚“或”关系???像是判断指定端口引脚的状态。。故查看库源代码。。。

以下是gpio.c文件中函数:
uint8_t GPIO_getInputPinValue(uint8_t selectedPort,
                              uint16_t selectedPins) {
    uint16_t baseAddress = GPIO_PORT_TO_BASE[selectedPort];

    #ifndef NDEBUG
    if(baseAddress == 0xFFFF)
    {
        return;
    }
    #endif

    // Shift by 8 if port is even (upper 8-bits)
    if((selectedPort & 1) ^ 1)
    {
        selectedPins <<= 8;
    }

    uint16_t inputPinValue = HWREG16(baseAddress + OFS_PAIN) & (selectedPins);

    if(inputPinValue > 0)
    {
        return (GPIO_INPUT_PIN_HIGH);
    }
    return (GPIO_INPUT_PIN_LOW);
}
这里返回的是GPIO_INPUT_PIN_HIGH or   GPIO_INPUT_PIN_LOW  不是 inputPinValue。

以下是gpio.h中函数声明及函数说明:
//*****************************************************************************
//
//! \brief This function gets the input value on the selected pin
//!
//! This function gets the input value on the selected pin.
//!
//! \param selectedPort is the selected port.
//!        Valid values are:
//!        - \b GPIO_PORT_P1
//!        - \b GPIO_PORT_P2
//!        - \b GPIO_PORT_P3
//!        - \b GPIO_PORT_P4
//!        - \b GPIO_PORT_P5
//!        - \b GPIO_PORT_P6
//!        - \b GPIO_PORT_P7
//!        - \b GPIO_PORT_P8
//!        - \b GPIO_PORT_P9
//!        - \b GPIO_PORT_P10
//!        - \b GPIO_PORT_P11
//!        - \b GPIO_PORT_PA
//!        - \b GPIO_PORT_PB
//!        - \b GPIO_PORT_PC
//!        - \b GPIO_PORT_PD
//!        - \b GPIO_PORT_PE
//!        - \b GPIO_PORT_PF
//!        - \b GPIO_PORT_PJ
//! \param selectedPins is the specified pin in the selected port.
//!        Valid values are:
//!        - \b GPIO_PIN0
//!        - \b GPIO_PIN1
//!        - \b GPIO_PIN2
//!        - \b GPIO_PIN3
//!        - \b GPIO_PIN4
//!        - \b GPIO_PIN5
//!        - \b GPIO_PIN6
//!        - \b GPIO_PIN7
//!        - \b GPIO_PIN8
//!        - \b GPIO_PIN9
//!        - \b GPIO_PIN10
//!        - \b GPIO_PIN11
//!        - \b GPIO_PIN12
//!        - \b GPIO_PIN13
//!        - \b GPIO_PIN14
//!        - \b GPIO_PIN15
//!
//! \return One of the following:
//!         - \b GPIO_INPUT_PIN_HIGH
//!         - \b GPIO_INPUT_PIN_LOW
//!         \n indicating the status of the pin
//
//*****************************************************************************
extern uint8_t GPIO_getInputPinValue(uint8_t selectedPort,
                                     uint16_t selectedPins);

首先作者说了GPIO_getInputPinValue函数的selectedPins是所选端口上的管脚。其掩码值可以是GPIO_PIN0GPIO_PIN1、GPIO_PIN2……GPIO_PIN15等十六个值的逻辑或
但是从头文件gpio.h函数中是这样的说的://! \param selectedPins is the specified pin in the selected port.   
不像其他函数:例如extern void GPIO_clearInterrupt(uint8_t selectedPort,
                                uint16_t selectedPins);
//! \param selectedPins is the specified pin in the selected port.
//!        Mask value is the logical OR of any of the following:

所以文中作者是不是写错了???


使用特权

评论回复
133
112207301219| | 2015-3-30 21:39 | 只看该作者
本帖最后由 112207301219 于 2015-3-30 21:48 编辑

if((selectedPort & 1) ^ 1)。这个是库函数gpio.c中函数GPIO_interruptEdgeSelect()中的一句话,不太明白意图,难道只是判断奇偶?还有GPIO_interruptEdgeSelect()这个函数是如何区分传入GPIO_PORT_P1和 GPIO_PORT_PA 这两个参数的呢?

下面是整个函数体
void GPIO_interruptEdgeSelect(uint8_t selectedPort,
                              uint16_t selectedPins,
                              uint8_t edgeSelect) {
    uint16_t baseAddress = GPIO_PORT_TO_BASE[selectedPort];

    #ifndef NDEBUG
    if(baseAddress == 0xFFFF)
    {
        return;
    }
    #endif

    // Shift by 8 if port is even (upper 8-bits)
    if((selectedPort & 1) ^ 1)
    {
        selectedPins <<= 8;
    }

    if(GPIO_LOW_TO_HIGH_TRANSITION == edgeSelect)
    {
        HWREG16(baseAddress + OFS_PAIES) &= ~selectedPins;
    }
    else
    {
        HWREG16(baseAddress + OFS_PAIES) |= selectedPins;
    }
}

使用特权

评论回复
134
hanzhenfei| | 2015-3-30 22:34 | 只看该作者
本帖最后由 hanzhenfei 于 2015-3-30 22:40 编辑
112207301219 发表于 2015-3-30 21:39
if((selectedPort & 1) ^ 1)。这个是库函数gpio.c中函数GPIO_interruptEdgeSelect()中的一句话,不太明白 ...

我刚开始和你一样困惑,不知道分析可对。

#define HWREG16(x)   (*((volatile uint16_t *)((uint16_t)x)))


if((selectedPort & 1) ^ 1)  这句话所有的GPIO函数都用到了,个人感觉是先判断端口是奇数端口还是偶数端口,
如果是奇数,不区分是GPIO_PORT_P1或是GPIO_PORT_PA,所操作的寄存器直接对对应selectedPins进行操作,不执行  selectedPins <<= 8;
如果是偶数端口需要移位执行selectedPins <<= 8;    GPIO_PORT_P1和GPIO_PORT_P2传递的基地址相同!!!!
这里全部都按照16位地址操作的!!!!!
主要原因是因为HWREG16(X)宏定义。
HWREG16(baseAddress + OFS_PAIES) &= ~selectedPins;  //

uint16_t baseAddress = GPIO_PORT_TO_BASE[selectedPort];  //我跟踪一下GPIO_PORT_P1和GPIO_PORT_P2传递的基地址相同
static const uint16_t GPIO_PORT_TO_BASE[] = {
    0x00,
#if defined(__MSP430_HAS_PORT1_R__)
    __MSP430_BASEADDRESS_PORT1_R__,
#elif defined(__MSP430_HAS_PORT1__)
    __MSP430_BASEADDRESS_PORT1__,
#else
    0xFFFF,
#endif
#if defined(__MSP430_HAS_PORT2_R__)
    __MSP430_BASEADDRESS_PORT2_R__,
#elif defined(__MSP430_HAS_PORT2__)
    __MSP430_BASEADDRESS_PORT2__,
#else
    0xFFFF,

。。。。。}

使用特权

评论回复
135
feiting94| | 2015-3-30 23:03 | 只看该作者
112207301219 发表于 2015-3-30 21:18
我也认为应该只有3个。不过或许是预留的,手册中说有些器件可能其他的端口也有中断功能。但是要预留的话 ...

握手,同感

使用特权

评论回复
136
112207301219| | 2015-3-31 00:03 | 只看该作者
hanzhenfei 发表于 2015-3-30 22:34
我刚开始和你一样困惑,不知道分析可对。

#define HWREG16(x)   (*((volatile uint16_t *)((uint16_t)x)) ...

感谢你的回答,有些语法我还不太熟,没完全看明白,我再仔细研究研究。看了你的解释后,我有看了几遍gpio.c和gpio.h。我目前的理解是,P1和PA的基地址和偏移地址都是一样的,操作字还是字节,取决于变量selectedPins,这是一个16位的变量,传入一个16位数时就是按字操作,传入一个8位数时就是按字节操作,此时高八位为0。因为是直接送到了映射的地址中,所以不用在程序中加判断语句。不知我的理解是否正确。

使用特权

评论回复
137
hanzhenfei| | 2015-3-31 08:05 | 只看该作者
本帖最后由 hanzhenfei 于 2015-3-31 08:19 编辑

大家相互学习,port2(高8位)和port1(低8位)组成PORTA(16位)。如果操作port2需要将数据移到高8位。操作port1和porta数据不需要移位了。port1和port2的selectpin是0~7。  porta的selectpin为0~15.  

使用特权

评论回复
138
hanzhenfei| | 2015-3-31 08:19 | 只看该作者
112207301219 发表于 2015-3-31 00:03
感谢你的回答,有些语法我还不太熟,没完全看明白,我再仔细研究研究。看了你的解释后,我有看了几遍gpio ...

大家相互学习,port2(高8位)和port1(低8位)组成PORTA(16位)。如果操作port2需要将数据移到高8位。操作port1和porta数据不需要移位了。port1和port2的selectpin是0~7。  porta的selectpin为0~15.

使用特权

评论回复
139
gaoyang9992006| | 2015-3-31 08:53 | 只看该作者
112207301219 发表于 2015-3-30 21:18
我也认为应该只有3个。不过或许是预留的,手册中说有些器件可能其他的端口也有中断功能。但是要预留的话 ...

最新版中已经解决了该问题,统一了。

使用特权

评论回复
140
jakecumt| | 2015-3-31 09:47 | 只看该作者
我想问一下使用库函数会不会影响代码的执行效率

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则