Embedded 当我们将0写入GPIO时会发生什么
我想知道当我们将“0”写入GPIO时会发生什么情况(实际的目的是拉低输出) 我不确定控制器是否拉下GPIO引脚并将其内部连接至接地,或者它只是在内部断开该引脚并使其与微控制器连接的外围设备(LED)断开 我的实际任务是: 我必须从4个gpio引脚(例如PORTA4-7)发送8位数据。所以要做到这一点,我必须先写高位(D4-D7),然后再写(D0-D3) 我的做法是:Embedded 当我们将0写入GPIO时会发生什么,embedded,avr,gpio,Embedded,Avr,Gpio,我想知道当我们将“0”写入GPIO时会发生什么情况(实际的目的是拉低输出) 我不确定控制器是否拉下GPIO引脚并将其内部连接至接地,或者它只是在内部断开该引脚并使其与微控制器连接的外围设备(LED)断开 我的实际任务是: 我必须从4个gpio引脚(例如PORTA4-7)发送8位数据。所以要做到这一点,我必须先写高位(D4-D7),然后再写(D0-D3) 我的做法是: % Writing the higher bits first PORTA=PORTA|(DATA & 0xF0); %
% Writing the higher bits first
PORTA=PORTA|(DATA & 0xF0);
%Writing the lower bits
PORTA=PORTA|((DATA & 0x0F)<<4);
%先写入高位
PORTA=PORTA |(数据&0xF0);
%写入低位
PORTA=PORTA |((DATA&0x0F)MCU将主动驱动引脚降低,您可以将其视为引脚接地
这不会影响4个较低的管脚,但仍然不正确。如果PORTA已设置为高且数据包含零,则不会将管脚设置为低。您希望屏蔽数据的相关部分,并且只希望保留PORTA中未更改的部分:
PORTA = (PORTA & 0x0F) | (DATA & 0xF0);
然后类似地设置4 lsb:
PORTA = (PORTA & 0xF0) | (DATA & 0x0F);
MCU将主动驱动引脚降低,您可以将其视为引脚接地
这不会影响4个较低的管脚,但仍然不正确。如果PORTA已设置为高且数据包含零,则不会将管脚设置为低。您希望屏蔽数据的相关部分,并且只希望保留PORTA中未更改的部分:
PORTA = (PORTA & 0x0F) | (DATA & 0xF0);
然后类似地设置4 lsb:
PORTA = (PORTA & 0xF0) | (DATA & 0x0F);
是的,写入PORTA将干扰所有位,即使其中一些位是DDRA指定的输入
在读取低位的ADC读数时,必须确保没有写入高位
甚至像
% Writing the higher bits first
PORTA=PORTA|(DATA & 0xF0);
%Writing the lower bits
PORTA=PORTA|((DATA & 0x0F)<<4);
%先写入高位
PORTA=PORTA |(数据&0xF0);
%写入低位
PORTA=PORTA |((DATA&0x0F)是,写入PORTA将干扰所有位,即使其中一些位是DDRA指定的输入
在读取低位的ADC读数时,必须确保没有写入高位
甚至像
% Writing the higher bits first
PORTA=PORTA|(DATA & 0xF0);
%Writing the lower bits
PORTA=PORTA|((DATA & 0x0F)<<4);
%先写入高位
PORTA=PORTA |(数据&0xF0);
%写入低位
PORTA=PORTA |((DATA&0x0F)了解GPIO是如何耦合在一起的最好方法就是访问数据表。TI的MSP430数据表就是一个很好的例子
输入/输出部分对GPIO寄存器如何与IO焊盘交互进行了非常明确的说明。以下是端口P1.0-p.17(来自上面数据表的第80页)
输出
这里给你的基本收获是:
- 如果IO焊盘处于输出模式,则将“0”写入P1OUT.x(例如,位0为P1OUT.0)将使输出变低
下面是一个更简单的简化版本:
输入
同样,这里是在“输入”模式下使用IO板的检查
这里的基本要点是写入P1OUT.x对输出没有影响;输出缓冲区是三态的
危险
如果你的程序在几个任务中共享一个GPIO端口登记器,那么你必须确保对这个登记器的访问是“强>线程安全< /强>。对于嵌入式系统,这通常意味着确保ISR不要把事情搞砸。”
//... (from main thread)
P1OUT = P1OUT | 0x02;
//... (from some ISR)
P1OUT = P1OUT | 0x01;
这通常转化为以下内容:
//... (from main thread)
mov P1OUT, %some_reg
operate on %some_reg
mov %some_reg, P1OUT
//... (from some ISR)
mov P1OUT, %some_reg
operate on %some_reg
mov %some_reg, P1OUT
//and then the time series looks like (P1OUT = 0 initially)
[0]: mov P1OUT, %some_reg_main_thread (%reg_m = 0)
[1]: or 0x02, %some_reg_main_thread (%reg_m = 2)
[2]: ISR fires!
[3]: mov P1OUT, %some_reg_isr_thread (%reg_i = 0)
[4]: or 0x01, %some_reg_isr_thread (%reg_i = 1)
[5]: mov %some_reg_isr_thread, P1OUT (P1OUT = 1)
[6]: ISR exits
[7]: mov %some_reg_main_thread, P1OUT (P1OUT = 2)
(end result: P1OUT=2, but should be 3 (0x01 | 0x02))
此外,IO板并不像看上去那么简单,你应该经常查看数据表,了解它到底有多糟糕/微妙/混乱/等等
例如,在上面的TI示例中,以下危险适用于您的原始问题:
(当P1DIR.x=0时)
- P1REN.x+P1OUT.x
- 如果P1REN.x为“1”,并且您切换P1OUT.x,这也会切换上拉电阻器的开和关
当然,IO pad拓扑是特定于MCU的。我建议在继续您的项目之前,先查看数据表中的IO pad拓扑。它应该是您最好的朋友
代码实践
如果可以,请考虑使用|=、&=和^=运算符,例如:
P1OUT |= (1<<2)+(1<<3) //assert pin2 & pin3 high
没有什么比gpio互相碰撞更糟糕的了!了解gpio是如何耦合在一起的最好方法就是访问数据表。TI的MSP430数据表就是一个很好的例子
输入/输出部分对GPIO寄存器如何与IO焊盘交互进行了非常明确的说明。以下是端口P1.0-p.17(来自上面数据表的第80页)
输出
这里给你的基本收获是:
- 如果IO焊盘处于输出模式,则将“0”写入P1OUT.x(例如,位0为P1OUT.0)将使输出变低
下面是一个更简单的简化版本:
输入
同样,这里是在“输入”模式下使用IO板的检查
这里的基本要点是写入P1OUT.x对输出没有影响;输出缓冲区是三态的
危险
如果你的程序在几个任务中共享一个GPIO端口登记器,那么你必须确保对这个登记器的访问是“强>线程安全< /强>。对于嵌入式系统,这通常意味着确保ISR不要把事情搞砸。”
//... (from main thread)
P1OUT = P1OUT | 0x02;
//... (from some ISR)
P1OUT = P1OUT | 0x01;
这通常转化为以下内容:
//... (from main thread)
mov P1OUT, %some_reg
operate on %some_reg
mov %some_reg, P1OUT
//... (from some ISR)
mov P1OUT, %some_reg
operate on %some_reg
mov %some_reg, P1OUT
//and then the time series looks like (P1OUT = 0 initially)
[0]: mov P1OUT, %some_reg_main_thread (%reg_m = 0)
[1]: or 0x02, %some_reg_main_thread (%reg_m = 2)
[2]: ISR fires!
[3]: mov P1OUT, %some_reg_isr_thread (%reg_i = 0)
[4]: or 0x01, %some_reg_isr_thread (%reg_i = 1)
[5]: mov %some_reg_isr_thread, P1OUT (P1OUT = 1)
[6]: ISR exits
[7]: mov %some_reg_main_thread, P1OUT (P1OUT = 2)
(end result: P1OUT=2, but should be 3 (0x01 | 0x02))
此外,IO板并不像看上去那么简单,你应该经常查看数据表,了解它到底有多糟糕/微妙/混乱/等等
例如,在上面的TI示例中,以下危险适用于您的原始问题:
(当P1DIR.x=0时)
- P1REN.x+P1OUT.x
- 如果P1REN.x为“1”,并且您切换P1OUT.x,这也会切换上拉电阻器的开和关