GPIO(外部上拉、外部下拉、外部没有上下拉的判断)

 

外部上拉下拉的意思:

For GPIO-IN pin, we can read its status through function DalTlmm_GpioIn(), but it is not easy tell whether it
is pulled or driven externally. This software solution can be used for such purpose.
Answer:
We will rely on the following logic to judge how GPIO is pulled/driven externally.
1. If we set GPIO to INPUT, INTERNAL PULL_UP, GPIO_IN read high. If we set GPIO INPUT, 
INTERNAL PULL_DOWN, GPIO_IN read high. Then, we can tell that GPIO is pulled/driven high from 
outside.
2. If we set GPIO to INPUT, INTERNAL PULL_UP, GPIO_IN read low. If we set GPIO INPUT, 
INTERNAL PULL_DOWN, GPIO_IN read low. Then, we can tell that GPIO is pulled/driven low from 
outside.
3. If we set GPIO to INPUT, INTERNAL PULL_UP, GPIO_IN read high. If we set GPIO INPUT, 
INTERNAL PULL_DOWN, GPIO_IN read low. Then, we can tell that GPIO is not pulled/driven from 
outside.

怎么判断是否有上拉货下拉:

//Configure internal pull up and Enable GPIO, DET_PIN_A_PU: internal pull up DalTlmm_ConfigGpio(
handle, (uint32)DET_PIN_A_PU, DAL_TLMM_GPIO_ENABLE);
//Delay 10ms
rex_sleep(10);
//Read GPIO to value1
DalTlmm_GpioIn(handle, (DALGpioSignalType)DET_PIN_A_PU, &value1);
// Configure internal pull down and Enable GPIO, DET_PIN_A_PD: internal pull down 
DalTlmm_ConfigGpio(handle, (uint32)DET_PIN_A_PD, DAL_TLMM_GPIO_ENABLE);
// Delay 10ms
rex_sleep(10);
// Read GPIO to value2
DalTlmm_GpioIn(handle, (DALGpioSignalType)DET_PIN_A_PD, &value2);
// Judge value1 and value2 to know how is this GPIO pulled/driven externally:
if((value1==DAL_GPIO_HIGH_VALUE)&&(value2==DAL_GPIO_HIGH_VALUE))
{
//GPIO is pulled/driven high externally
GPIN_IN_value = GPIO_EXTERNAL_DRIVEN_HIGH; } else if((value1==DAL_GPIO_LOW_VALUE)&
&(value2==DAL_GPIO_LOW_VALUE))
{
//GPIO is pulled/driven low externally
GPIN_IN_value = GPIO_EXTERNAL_DRIVEN_LOW; } else if((value1==DAL_GPIO_HIGH_VALUE)&
&(value2==DAL_GPIO_LOW_VALUE))
{
//GPIO is not pulled/driven externally
GPIN_IN_value = GPIO_EXTERNAL_NO_DRIVEN; 
}

 

we will rely on the following logic to judge how GPIO is pulled/driven externally.
1. If we set GPIO to INPUT, INTERNAL PULL_UP, GPIO_IN read high. If we set GPIO INPUT,
INTERNAL PULL_DOWN, GPIO_IN read high. Then, we can tell that GPIO is pulled/driven high from
outside.
2. If we set GPIO to INPUT, INTERNAL PULL_UP, GPIO_IN read low. If we set GPIO INPUT,
INTERNAL PULL_DOWN, GPIO_IN read low. Then, we can tell that GPIO is pulled/driven low from
outside.
3. If we set GPIO to INPUT, INTERNAL PULL_UP, GPIO_IN read high. If we set GPIO INPUT,
INTERNAL PULL_DOWN, GPIO_IN read low. Then, we can tell that GPIO is not pulled/driven from
outside.

使用GPIOs: 要使用GPIO,系统首先要分配一个GPIO,使用gpio_request() 为系统分配一个GPIO,接下来要做的一件事是标示GPIO的方向,通常在使用GPIO建立一个platform_device时(位于单板的setup代码中):

 /* set as input or output, returning 0 or negative errno */
 int gpio_direction_input(unsigned gpio);
int gpio_direction_output(unsigned gpio, int value)

返回0标示成功,或是一个负的errno错误码。它应该被检查,因为get/set调用没有错误返回,且可能会有错误配置。你通常应该在线程上下文中使用这些调用。

Spinlock-Safe GPIO访问
大多数GPIO控制器可以使用内存读写指令访问。它们不需要休眠,且可以从内部硬件中断处理(非线程)和类似的上下文环境安全完成。
使用下列调用访问这些GPIO,此时gpio_cansleep将总是返回错误

 /* GPIO INPUT:  return zero or nonzero */
 int gpio_get_value(unsigned gpio);

 /* GPIO OUTPUT */
 void gpio_set_value(unsigned gpio, int value);

其中,value是一个布尔型参数,零表示低,非零表示高。当读一个输出管脚的值时,返回的值应该是在管脚上看到的值...这并不总是与指定输出值相匹配的,因为存在开漏信号和输出延迟问题。

可能睡眠的GPIO访问:
一些GPIO控制器必须使用基于消息的总线如I2C和SPI来进行访问。读写这些GPIO的命令需要等待到达发送队列的开始和获取它的响应。这需要休眠,且不能从内部中断处理函数中完成。

对于这种GPIO调用gpio_cansleep接口将返回非零值(需要一个有效的GPIO号码,并已经提前使用gpio_request进行分配)

int gpio_cansleep(unsigned gpio);

为了访问这些GPIO,一个不同的访问函数集被定义

 /* GPIO INPUT:  return zero or nonzero, might sleep */
 int gpio_get_value_cansleep(unsigned gpio);

 /* GPIO OUTPUT, might sleep */
 void gpio_set_value_cansleep(unsigned gpio, int value);


访问这样的gpio需要一个可能睡眠的上下文,例如一个线程级别中断处理程序,并且这些访问函数必须代替那些没有cansleep()后缀的spinlock-safe的函数。  

考虑到大多数场景中GPIO在它们被声明后实际已经被正确配置,定义了3各附加的调用:

 /* request a single GPIO, with initial configuration specified by
  * 'flags', identical to gpio_request() wrt other arguments and
  * return value
  */
 int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);

 /* request multiple GPIOs in a single call
  */
 int gpio_request_array(struct gpio *array, size_t num);

 /* release multiple GPIOs in a single call
  */
 void gpio_free_array(struct gpio *array, size_t num);

其中,flags参数当前可以指定为下列属性:

 * GPIOF_DIR_IN - 配置方向为输入
 * GPIOF_DIR_OUT - 配置方向为输出

 * GPIOF_INIT_LOW - 作为输出,设置初始值为低
 * GPIOF_INIT_HIGH - 作为输出,设置初始值为高
 * GPIOF_OPEN_DRAIN - GPIO管脚是开漏极形式
 * GPIOF_OPEN_SOURCE - GPIO管脚是开源极形式


由于GPIOF_INIT_*仅仅当配置为输出时有效,所以有效组合为
 * GPIOF_IN - 配置为输入
 * GPIOF_OUT_INIT_LOW - 配置为输出,初始为低电平
 * GPIOF_OUT_INIT_HIGH - 配置为输入,初始为高电平

当设置flag为GPIOF_OPEN_DRAIN时,它将假设管脚是开漏极方式。这类管脚在输出模式将不会被驱动为1。

这样的管脚需要连接上拉。通过使能此flag,当它在输出模式被要求设置为1时,gpio lib将使得方向为输入以使得管脚变高。输出模式下,管脚输出值0以驱动电平为低。

当设置flag为GPIOF_OPEN_SOURCE,它假设管脚时开源极类型。这种管脚在输出模式不能驱动为0。此种管脚需要下拉。通过使能这个flag,当管脚要求输出1时,gpio lib将使得方向变为输入以使得管脚变低。管脚在输出模式驱动1为高  
 

 

posted @ 2021-07-06 23:25  皮特99  阅读(920)  评论(0编辑  收藏  举报