求一个同时读取8个IO输入的操作(PF0-PF7)

2019-07-20 08:10发布

求一个同时读取8个IO输入的操作(PF0-PF7),然后把他们放到一个 内存中,用16进制表示。自己是这样实现的

unsigned char  data=0;
data =GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_7);//8位
   data << 1;
   data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_6);//7位
   data << 1;
   data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_5);//6位
   data << 1;
   data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_4);//5位
   data << 1;
   data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_3);//4位
   data << 1;
   data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_2);//3位
   data << 1;
   data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_1);//2位
   data << 1;
   data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_0);//1位

这样很浪费时间,没有一起直接操作的吗?就像发送这样
#define Dataout(x)   GPIO_Write(GPIOF,x)   //声明低8位输出
直接操作Dataout(data) 就好了

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
14条回答
likunxue
1楼-- · 2019-07-21 10:46
 精彩回答 2  元偷偷看……
貌似大神
2楼-- · 2019-07-21 11:18
 精彩回答 2  元偷偷看……
貌似大神
3楼-- · 2019-07-21 12:54
屋脊雀 发表于 2018-5-14 20:36
大哥,你还是不明白,这个函数怎么会影响你的资源呢?
PF0-PF7接按键输入
PF8-PF15其他,随便,做什么 ...

首先,函数可以用,是肯定的。换个问题吧,如果16个全是输入模式,我只要低八位呢?因为项目后面很可能要继续加东西,比如又需要一组输入IO,那这种方法就要换了。(IO口用的差不多了)
屋脊雀
4楼-- · 2019-07-21 18:53
 精彩回答 2  元偷偷看……
mack13013
5楼-- · 2019-07-21 21:11
本帖最后由 mack13013 于 2018-5-15 19:27 编辑
貌似大神 发表于 2018-5-15 14:24
非常感谢。你说的,道理我懂,目前的确用不到高八位,所以我说可以使用。重点在于担心以后,可能也要用他 ...

哎,回复你这个帖子真是费了我的劲了,本来想简简单单说一下,又怕你再有疑问,索性多花点功夫做个全科普吧,累。

第一,给你看一下GPIO结构,下图就是GPIO结构,并且我在图上做简单标示:
IO.jpg

(补充一下:图片上下面的红字的意思是:输出寄存器对IO引脚的影响,要受输出控制和输出控制后面的推挽结构控制。简单的说,输出寄存器想要影响IO状态,还要看输出控制、推挽结构答不答应)

每一个IO引脚都有上图那么一个结构,并且同一组引脚的输入寄存器和输出寄存器在地址上是连续的,比如PF0-PF15的IDR地址上连续,ODR地址上也连续,PE0-PE15也是如此,为什么这样设计呢?
这样设计,在操作上是可以“一次”读取的,比如我要获取PF0-PF15的IO输入状态,那么我直接u16 uwPFStatus = GPIOF->IDR;这样我通过一条语句就把PF的16个引脚状态读取完成。

有人说,我只想读取某些引脚状态,不想全读,是不是可以?比如LZ一楼所做的操作:分8次分别读取PF0-PF7的状态,LZ的代码如下:
[mw_shl_code=c,true]data =GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_7);//8位
   data << 1;
    data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_6);//7位
   data << 1;
    data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_5);//6位
   data << 1;
    data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_4);//5位
   data << 1;
    data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_3);//4位
   data << 1;
    data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_2);//3位
   data << 1;
    data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_1);//2位
   data << 1;
    data |= GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_0);//1位[/mw_shl_code]

哎,想法很好,没什么用,而且可能做了不必要的操作。我们来看下GPIO_ReadInputDataBit这个函数是个什么鬼,这个函数在stm32fXxx_gpio.c中如下:
[mw_shl_code=c,true]@endverbatim
  * @{
  */

/**
  * @brief  Reads the specified input port pin.
  * @param  GPIOx: where x can be (A..K) to select the GPIO peripheral for STM32F405xx/407xx and STM32F415xx/417xx devices
  *                      x can be (A..I) to select the GPIO peripheral for STM32F42xxx/43xxx devices.
  *                      x can be (A, B, C, D and H) to select the GPIO peripheral for STM32F401xx devices.
  * @param  GPIO_Pin: specifies the port bit to read.
  *         This parameter can be GPIO_Pin_x where x can be (0..15).
  * @retval The input port pin value.
  */
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  uint8_t bitstatus = 0x00;

  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

  if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
  {
    bitstatus = (uint8_t)Bit_SET;
  }
  else
  {
    bitstatus = (uint8_t)Bit_RESET;
  }
  return bitstatus;
}[/mw_shl_code]

这里面有这么一句:
  if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
也就是说,这个函数最终还是读取GPIOF->IDR(另外,也看出了,库函数里面还是操作寄存器),并且LZ那样写代码是更加繁琐
(本来读取IDR一次就完成了,LZ读取了8次,也就是说LZ的读取不是”同时“,如果在LZ读取这8次信号的时候,信号发生了变化...)

所以LZ要达成的目的更准确的方法是这样:u16 uwPFStatusIn = GPIOF->IDR;,但是LZ又说了,他只想要低8位,那就这样:
u8 ucPFLowByteIn = GPIOF->IDR & 0xFF;当然,如果遇到类型不匹配错误或者警告自行添加强制转换就可以了。

至于LZ说的要把高8位用做他出,这个也简单,如果是复用,直接操作复用寄存器,如果高8位当作IO输入或者输出,直接操作对应的寄存器:
输入:
u8 ucPFHighByteIn = (GPIOF->IDR >> 8)  & 0xFF;
或者
u16 uwPFHighWordIn =  GPIOF->IDR & 0xFF00;

输出:
u16 uwPFHighByteOut = xx;//(xx是你要设置的状态)
GPIOF->ODR &= 0xFFFF00FF;//擦除高8位状态
GPIOF->ODR |= uwPFHighByteOut;//想一下uwPFHighByteOut应该怎么构造?


留下几个思考坑:
1、IO结构图中施密特那里的开关是指开关控制,还是指开关信号(数字信号)?
2、无论IDR还是ODR,都是32位的噢,呵呵,why?
3、GPIO_TypeDef??????这个东西有什么用?为什么这么用?
4、不考虑Verilog语言特性,FPGA在物理结构上一个最小单元是什么样的(实际上非常复杂)?相应的,STM32之类的MCU的微电子制造结构?
5、现在看的话,是不是应该入门学寄存器,熟稔之后寄存器和库函数随便选?而且学习寄存器版本,只需要学一个流水灯就够了(有充分的数
电基础,一个流水灯就足够了解STM32开发的底层原理了,然后寄存器和库函数自己选)。
6、输出、输入的上、下拉;输出的推挽,以及输入的浮空如何实现的?


另外:代码我随手在网页上打的,数据类型转换,错误检查什么的没做,请大家不要在意这些细节,让我完美装逼。。。





貌似大神
6楼-- · 2019-07-22 02:18
mack13013 发表于 2018-5-15 19:17
哎,回复你这个帖子真是费了我的劲了,本来想简简单单说一下,又怕你再有疑问,索性多花点功夫做个全科普 ...

非常感谢,没想到一个小小的问题,暴露了自己这么多的不足。之前忙着赶进度,就直接上手了,看来要加紧打牢一下基础。留下的问题,回去好好琢磨,最后再次感谢!麻烦了。

一周热门 更多>