C 无法使2个指示灯工作。[覆盆子皮,裸金属]
我面临的一个问题是让两个LED相继发光或同时发光。但是,它们一次只能单独工作一个。当我试图在同一个程序中实现这一点时,问题就来了。只有第一个LED开始闪烁,而不是另一个。 以下是我的代码:C 无法使2个指示灯工作。[覆盆子皮,裸金属],c,embedded,raspberry-pi,bare-metal,C,Embedded,Raspberry Pi,Bare Metal,我面临的一个问题是让两个LED相继发光或同时发光。但是,它们一次只能单独工作一个。当我试图在同一个程序中实现这一点时,问题就来了。只有第一个LED开始闪烁,而不是另一个。 以下是我的代码: #define GPFSEL1 0x20200004 #define GPFSEL2 0x20200008 #define GPSET0 0x2020001C #define GPCLR0 0x20200028 #define SET_PIN18_OUTPUT (0x01 << 24) /
#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);
}
#定义GPFSEL1 0x20200004
#定义GPFSEL2 0x20200008
#定义GPSET0 0x2020001C
#定义GPCLR0 0x20200028
#在notmain()
中定义SET\u PIN18\u输出(0x01,您从不调用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而不是无符号int。这样就不需要进行多次强制转换
在notmain()
中,您永远不会调用clearBit()
类型:
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而不是无符号int。这样就不需要进行多次强制转换
与“忙循环”相比,包括定时器硬件的使用效果更好。GPIO外围设备有单独的寄存器用于设置(GPSET0
)和清除(GPCLR0
)输出引脚,这样您就不必执行读-修改-写操作。写入GPSET寄存器仅设置1位,而0位保持不变。写入GPCLR寄存器仅清除1位,而0位保持不变
您不应该使用setBit()
和clearBit()
用于设置和清除GPIO输出的例程。这些例程可能适用于没有用于设置和清除位的单独寄存器的其他外围设备。但读-修改-写操作不适用于GPSET0
和GPCLR0
。事实上,读-修改-写操作可能实际上是so问题的根源。可能是GPSET0
和GPCLR0
在读取它们时总是返回0x00000000,因为根本不需要读取它们。(我不确定,我只是猜测。)
而不是调用setBit()
和clearBit()
要设置GPIO输出,您只需直接写入GPSET0
或GPCLR0
即可。写入前无需读取GPSET0
或GPCLR0
。因为写入时,只有设置为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);
//设置位
*(UINT32_P)GPSET0=(1GPIO外围设备有单独的寄存器用于设置(
GPSET0
)和清除(GPCLR0
)输出引脚,这样您就不必执行读-修改-写操作。写入GPSET寄存器仅设置1位,而0位保持不变。写入GPCLR寄存器仅清除1位,而0位保持不变
您不应该使用setBit()
和clearBit()
用于设置和清除GPIO输出的例程。这些例程可能适用于没有用于设置和清除位的单独寄存器的其他外围设备。但读-修改-写操作不适用于GPSET0
和GPCLR0
。事实上,读-修改-写操作可能实际上是so问题的根源。可能是GPSET0
和GPCLR0
在读取它们时总是返回0x00000000,因为根本不需要读取它们。(我不确定,我只是猜测。)
而不是调用setBit()
和clearBit()
要设置GPIO输出,您只需直接写入GPSET0
或GPCLR0
即可。写入前无需读取GPSET0
或GPCLR0
。因为写入时,只有设置为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);
//设置位
*(UINT32_P)GPSET0=(1每个GPIO引脚有3位来选择一个功能。您只设置三位中的一位,即最低位,而不设置高两位。因此,我猜在启动时,引脚18有功能0,引脚24有功能2(左右)。然后将引脚18配置为功能1,这样就可以工作,但引脚24配置为功能3,而功能3则不能工作
您应该编写一个函数“void setFunction(uint32_t pin,uint32_t fn)”,该函数根据pin加载GPFSEL0/GPFSEL1/GPFSEL2中的一个,屏蔽指定pin的3位,或fn中指定的3位,最后将其写回寄存器
我发现的另一件事,上面已经提到过,就是GPSET0/GPCLR0不需要读-修改-写。只需直接向它们写入要设置/清除的位。这不会影响任何其他位。每个GPIO引脚有3位来选择一个函数。您只需设置三位中的一位,即最低位,而只保留较高的两位。So我的猜测是,在启动时,插脚18具有功能0,插脚24具有功能2(大约)。然后,您将插脚18配置为功能1,使其工作,但插脚24配置为功能3,而功能3则不工作
您应该编写一个函数“void setFunction(uint32_t pin,uint32_t fn)”,该函数根据pin加载GPFSEL0/GPFSEL1/GPFSEL2中的一个,屏蔽指定pin的3位,或fn中指定的3位,最后将其写回寄存器
我发现的另一件事,上面已经提到过,就是GPSET0/GPCLR0不需要读-修改-写。只需直接向它们写入要设置/清除的位。这不会影响任何其他位。您最好