请问STM32怎么才能并行操作低八位的IO口或高八位的IO口?
比我我要操作PA0——PA8,我怎么才能一次操作这9个位而不影响PA9——PA15的IO口!单片机我知道是P0=0x00,就是全部拉低,可是STM32我试过用GPIOA-...
比我我要操作PA0——PA8,我怎么才能一次操作这9个位而不影响PA9——PA15 的IO口!单片机我知道是P0=0x00,就是全部拉低,可是STM32 我试过用GPIOA->ODR=0x0000;可是这样也影响了高PA9——PA15,我就是想把PA0——PA8分离出来,并行操作,因为我要这九个位做并口做5*4键盘扫描程序!请高手帮忙解答,我用的是直接操作寄存器,我暂时不想学库函数操作,最好用直接操作寄存器的方法!谢谢了
展开
6个回答
展开全部
您好,STM32的GPIO口的功能是非常之强大的。
关于GPIO输出的赋值可以使用两种方法,
方法A:逐个配置法,优点是不会影响到其它的GPIO口,缺点是操作比较繁琐。
方法B:ODR设置法,优点是操作轻松,缺点是需要硬件电路作配合。
下面我们详细描述这两种方法:
方法A:所谓逐个配置法, 就是对需要输出数据的IO口线逐个配置,
需要输出为1的IO口使用GPIOx->BSS = 1 << N; (N表示第N根线,如PA9, N值为9)
需要输出为0的IO口使用GPIOx->BRSS = 1 << N;
使用如下语句可以完成
//to do 先将输出口配置为输出功能
for( i = start; i < end; i++ )
{
if( value & 0x01 )
{ GPIOx->BSS = 1 << i; }
else
{ GPIOx->BRSS = 1 << i; }
}
方法B: ODR配置法,可以直接使用 GPIO->ODR = value << N;给对应的IO口进行输出操作。
但是此时在硬件上要保证:
1. 该功能口(如GPIOA)上的其余的IO口不作为普通的IO输出口使用(因为是键盘扫描,当列输出的时候,行应当是输入;同理,当列输入时,行应当是输出)
2. 行列之外的GPIO口,要么是普通的IO输入口,要么是功能口。功能口就是UART、USB、PWM、ADC等,对GPIO的ODR进行操作时,不会对功能口产生影响。
以上第2条是对第1条的详细解释。
总结:如果在硬件上可以满足方法B的应用条件,建议优先采用方法B。
在其它一些需要使用并行输出,如并口液晶、NandFlash等应该的时候,也可以考虑使用方法B。
关于GPIO输出的赋值可以使用两种方法,
方法A:逐个配置法,优点是不会影响到其它的GPIO口,缺点是操作比较繁琐。
方法B:ODR设置法,优点是操作轻松,缺点是需要硬件电路作配合。
下面我们详细描述这两种方法:
方法A:所谓逐个配置法, 就是对需要输出数据的IO口线逐个配置,
需要输出为1的IO口使用GPIOx->BSS = 1 << N; (N表示第N根线,如PA9, N值为9)
需要输出为0的IO口使用GPIOx->BRSS = 1 << N;
使用如下语句可以完成
//to do 先将输出口配置为输出功能
for( i = start; i < end; i++ )
{
if( value & 0x01 )
{ GPIOx->BSS = 1 << i; }
else
{ GPIOx->BRSS = 1 << i; }
}
方法B: ODR配置法,可以直接使用 GPIO->ODR = value << N;给对应的IO口进行输出操作。
但是此时在硬件上要保证:
1. 该功能口(如GPIOA)上的其余的IO口不作为普通的IO输出口使用(因为是键盘扫描,当列输出的时候,行应当是输入;同理,当列输入时,行应当是输出)
2. 行列之外的GPIO口,要么是普通的IO输入口,要么是功能口。功能口就是UART、USB、PWM、ADC等,对GPIO的ODR进行操作时,不会对功能口产生影响。
以上第2条是对第1条的详细解释。
总结:如果在硬件上可以满足方法B的应用条件,建议优先采用方法B。
在其它一些需要使用并行输出,如并口液晶、NandFlash等应该的时候,也可以考虑使用方法B。
更多追问追答
追问
方法二,怎么分离出其中九个IO口来实行并行操作呢?就是要51单片机那样直接P1=0x01这个样!
追答
我们以GPIOA作为示范吧
将GPIOA0~GPIOA3作为行,GPIOA4~GPIOA8作为列。
其余的IO口只能作为输入功能 或 功能口(如上面说的ADC、UART、IIC、PWM、SPI、USB等)。
当要向行输出数据 value 时,将列配置为输入,行配置为输出,然后使用GPIOA->ODR = value。
当要向列输出数据 value 时,将行配置为输出,列配置为输入,然后使用GPIOA->ODR = value << 4;
展开全部
建议还是用库函数。
库函数是官方发布的,是经过大量验证的,极少出BUG,可减少自己一点点从底层寄存器架构时产生的系统性不好和出错。
使用库函数可减少大量的对底层的操作,能节约很多精力。与其一位一位的去数寄存器的位,不如把时间花在如何提高代码质量,以及学习更高级的编程思想,比如RTOS。这对于提高薪资收入有绝对的帮助。
现在绝大多数公司都是使用库函数的,而你只会使用底层寄存器的写法,会阻碍你和别人的对接,进一步的也会降低你进入先进公司的机会。
8位的单片机现在已经处于淘汰状态,前几日我看到ST公司发布会的介绍,STM32的出货量去年一年已经达到2亿片,32位处理器淘汰8位的已经是大势所趋。所以为了不让将来处于被动,应该积极的学习先进的知识和方法,而不是固步自封的让自己守在8位机编程那种,对寄存器一位一位的操作方式上。
除非你在写8位机这方面有很特殊的技艺,你可以留在8位机编程的思想上,否则还是按实际需要和主流方式来做事才是正道。因为做产品,时间成本是重大因素,官方适时推出了库函数的目的就在于缩短开发的时间和难度。除非你是做学术、做研究。
以下是我用库函数写的一个并口操作,单片机型号:STM32F1系列
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
可以来简单的,比如你要向PA写9位数据z,那就这样:
GPIOA->ODR&=~0x01FF; //清零PA0~PA8
GPIOA->ODR|=z;
这是标准位操作,可惜很多人都不知道。
或者这样:
GPIOA->BRR=0x01FF; //清零PA0~8
GPIOA->BSRR=z;
GPIOA->ODR&=~0x01FF; //清零PA0~PA8
GPIOA->ODR|=z;
这是标准位操作,可惜很多人都不知道。
或者这样:
GPIOA->BRR=0x01FF; //清零PA0~8
GPIOA->BSRR=z;
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
ODR寄存器不能进行位操作,而BRSS寄存器则可以进行位操作。ODR我还没用过,大多都是用BRSS。给你举俩例子说说BRSS的用法吧。
操作PA9为1:GPIOA->BRSS=1<<9;
操作PA0为1:GPIO1->BRSS=1<<0;
操作PA9为1:GPIOA->BRSS=1<<9;
操作PA0为1:GPIO1->BRSS=1<<0;
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
/*gpio先配置为输出*/
void GPIOA_WriteLSB8bits(char data)
{
unsigned short buf;
buf = GPIOA->ODR;
buf = (buf & 0xff00) | data;
GPIOA->ODR = buf;
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询