c -无法获得2个led工作.[树莓派,裸金属]



我面临的问题是让2个led一个接一个或同时发光。然而,它们一次只能单独工作一个。当我试图在同一个程序中实现这一点时,问题就来了。只有第一个LED开始过滤,而不是另一个。下面是我的代码:

#define GPFSEL1 0x20200004
#define GPFSEL2 0x20200008
#define GPSET0  0x2020001C
#define GPCLR0  0x20200028
#define SET_PIN18_OUTPUT (0x01 << 24) // GPFSEL1
#define SET_PIN23_OUTPUT (0x01 << 9)  // GPFSEL2
#define SET_PIN24_OUTPUT (0x01 << 12) // GPFSEL2
#define SET_GPION(x)   (0x01 << x)
#define CLEAR_GPION(x) (0x01 << x)
#define NUM_OF_LEDS 3
//-------------------------------------------------------------------------
typedef unsigned int* UINT32_P;
void dummy(volatile unsigned int val)
{
  val++;
}
void setBit(unsigned int regAdd, unsigned char bit)
{
  unsigned int temp;
  temp  = *(UINT32_P)(regAdd);
  temp  |= (0x1 << bit);
  *(UINT32_P)(regAdd) = temp;
}
void clearBit(unsigned int regAdd, unsigned char bit)
{
  unsigned int temp;
  temp = *(UINT32_P)(regAdd);
  temp &= ~(1 << bit);
  *(UINT32_P)(regAdd) = temp;
}
int notmain ( void )
{
    unsigned int ra;
    setBit(GPFSEL1, 24);  // Configure PIN 18 to output
    setBit(GPFSEL2, 12);  // Configure PIN 24 to output
    while(1)
    {
    // L1 - -
    setBit(GPSET0, 18);
    setBit(GPSET0, 24);
    for(ra=0;ra<0x100000;ra++) dummy(ra);

    // - L2 -
    setBit(GPCLR0, 18);
    setBit(GPCLR0, 24);
    for(ra=0;ra<0x100000;ra++) dummy(ra);
    for(ra=0;ra<0x100000;ra++) dummy(ra);

    }
    return(0);
}

GPIO外设有单独的寄存器用于设置(GPSET0)和清除(GPCLR0)输出引脚,因此您不必进行读-修改-写操作。写入GPSET寄存器只设置为1的位,而0的位保持不变。写入GPCLR寄存器只清除为1的位,而为0的位保持不变。

您不应该使用setBit()clearBit()例程来设置和清除GPIO输出。这些例程可能适用于没有单独寄存器来设置和清除位的其他外设。但是读-修改-写操作不适合GPSET0GPCLR0。实际上,读-修改-写操作实际上可能是问题的根源。可能GPSET0GPCLR0在读取它们时总是返回0x00000000,因为不需要读取它们。(我不敢肯定,我只是猜测。)

而不是调用setBit()clearBit()来设置GPIO输出,你应该直接写入GPSET0GPCLR0。在写入GPSET0GPCLR0之前,您不需要读取它们。因为当你写入它们时,只有你设置为1的位会改变,你写为0的位会保持不变。

试试这样写:

// Set bits
*(UINT32_P)GPSET0 = (1 << 18);
*(UINT32_P)GPSET0 = (1 << 24);
// Clear bits
*(UINT32_P)GPCLR0 = (1 << 18);
*(UINT32_P)GPCLR0 = (1 << 24);

notmain()中不能调用clearBit(),只能调用setBit()

类型:

typedef unsigned int* UINT32_P;

应该声明为:

typedef volatile unsigned int* UINT32_P;

我建议把你的地址定义为指针而不是整数:

#define GPFSEL1 ((UINT32_P)0x20200004)
#define GPFSEL2 ((UINT32_P)0x20200008)
#define GPSET0  ((UINT32_P)0x2020001C)
#define GPCLR0  ((UINT32_P)0x20200028)

set/clearBit接受UINT32_P类型而不是unsigned int类型。这样就不需要多次强制类型转换了。

BCM2835包含定时器硬件,您可以比"忙环"更好地利用。

每个GPIO引脚有3位选择一个功能。您只设置三个位中的一个,即最低的位,而保留上面的两个位。所以我的猜测是,在启动引脚18有功能0和引脚24有功能2(或左右)。然后将引脚18配置为功能1,因此它可以工作,但将引脚24配置为功能3,这不起作用。

你应该写一个函数"void setFunction(uint32_t pin, uint32_t fn)",根据引脚,加载GPFSEL0/GPFSEL1/GPFSEL2中的一个,屏蔽掉指定引脚的3位,或在fn中指定的3位,最后将其写回寄存器。

我发现的另一件事(上面已经提到过)是GPSET0/GPCLR0不需要读-修改-写。只需直接将您想要设置/清除的位写入它们即可。它不会影响任何其他位

相关内容

  • 没有找到相关文章

最新更新