HOME
  Security
   Software
    Hardware
  
FPGA
  CPU
   Android
    Raspberry Pi
  
nLite
  Xcode
   etc.
    ALL
  
LINK
BACK
 

2023/04/14

STM32の内蔵プルアップには注意!? STM32の GPIOの内蔵 Pull-Upが人体の抵抗に負けて Lowになる件 STM32の内蔵プルアップには注意!? STM32の GPIOの内蔵 Pull-Upが人体の抵抗に負けて Lowになる件

(STM32 STM32F103C8T6 GPIO internal Pull-Up is defeated by human body resistance and become Low)

Tags: [ワンチップCPU]




● STM32の内蔵プルアップには注意!?

 STM32 GPIO internal Pull-Up is defeated by human body resistance and become Low

 6年ぶりに STM32F103C8T6を使って電子工作をした所、不可解な現象に悩みました。

 それは、STM32の GPIOの内蔵 Pull-Upが人体の抵抗に負けて Lowになると言うトラブルです。

 Arduinoで STM32F103C8T6用のテストプログラムを作成して動作確認をしたら、ボタンを押していないのに不定期に「押した」と判定してしまいます。
 ※ ボタンを配線しているピンに、乾燥した指で触れたり離したりする

 「なんで???」とプログラムを見直しても正しく INPUT_PULLUPを指定しています。
#define USER_BUTTON PB12

  pinMode(USER_BUTTON, INPUT_PULLUP);

 試しに INPUTの指定にして内蔵プルアップをオフにしたら、INPUT_PULLUPの時よりも頻繁に「押した」と判定します。
  pinMode(USER_BUTTON, INPUT);
 と言う事は INPUTと INPUT_PULLUPで明確に挙動に差が有るので INPUT_PULLUPは何かしら働いている?と思いましたが、今まで長い事電子工作をしてきて CPUに内蔵のプルアップ抵抗が人体の接触抵抗に「負ける」と言うトラブルに遭った事が無かったので信じられませんでした。

 Arduinoのライブラリのバグかな?と思いググルも明確な解決はできませんでした。
 勿論、下記を行なっても駄目でした。
  digitalWrite(USER_BUTTON, HIGH); // Enable Input built-in Pull-Up
 ※ STM32F103は入力時のプルアップ指定を GPIO出力のレジスタ(GPIOx_ODR)で行なうので理屈的には合っています(GPIOx_PUPDRレジスタは存在しない)

 と言う事で、今度は障害の切り分けとして STM32の公式の開発ツール STM32CubeIDEで同様のプログラムを作成して動作確認しました。
STM32CubeIDE STM32用統合開発環境

 結果としては Arduinoの時と同じで、ボタンを押していないのに「押した」と判定してしまいます。
 ※ 同じく、ボタンを配線しているピンに、乾燥した指で触れたり離したりする

 GPIO_InitStruct.Pullの GPIO_PULLUPを GPIO_NOPULLにして内蔵プルアップをオフにしたら、GPIO_PULLUPよりも頻繁に「押した」と判定します。(これも Arduinoの時と同じ)

 と言う事で、
 Arduinoの INPUT_PULLUPは正しく機能している
 STM32の内蔵プルアップ抵抗は「人体の接触抵抗に負ける」
 と言う結論に成りました。

 STM32を使った製作物で、ケースに組み込んだ場合は大丈夫と思いますが、基板のままで配線がむき出しの物は注意が必要と思います。

 明示的にプルアップ抵抗(4.7k~10kΩ程度)を実装した方が安全です。

 私の場合、入力系は負論理入力を好みます。つまり、スイッチを離した状態はプルアップの HIGHレベル、スイッチを押した状態は GNDに接続し LOWレベル。LOWレベルがアクティブなので「負論理」。

 同じく、出力系も負論理で、LED等はアノードを電源に接続して、カソードを GPIOの出力ピンに接続します。その状態でGPIOを LOWを出力で点灯(LEDの駆動電流を吸い込む)、HIGHを出力で消灯です。
 (GPIOの出力方法はオープンドレインでも大丈夫、と言うかオープンドレインの方が好ましいです)

 ちなみに「人体の抵抗」でググッたら皮膚が乾燥状態では 2k~5kΩと言う事です。汗や水等で湿った状態では 2kΩ以下と言う事です。(サイト毎に記載の値は異なる)

 私がテスターで人体の抵抗値を実測した所、下記の様になりました。
片方の手の親指と人差し指で両方のテスター棒を強くつまむ
(テスター棒同士は 5mm程度離す)
10MΩ
両方の手の親指と人差し指でそれぞれのテスター棒を強くつまむ10MΩ
両方の手の親指と人差し指を水で軽く湿らせてそれぞれのテスター棒を強くつまむ5MΩ
片方の手の親指と人差し指でテスター棒を強くつまみ、もう片方のテスター棒を足の指の腹に強く押し当てる15MΩ
片方の手の親指と人差し指でテスター棒を強くつまみ、もう片方のテスター棒を同じ手の甲に強く押し当てる導通無し(接触面積の関係っぽい)
 STM32のボタンの誤判定の原因は抵抗ではなく静電気や静電容量?



● STM32の GPIOの内蔵プルアップ抵抗の関連の資料

 GPIOの内蔵プルアップ抵抗は標準で 40kΩ

STM32F103x8 Datasheet
 5.3.13 I/O port characteristics
 RPU Weak pull-up equivalent resistor 標準 40kΩ

・Table 35. I/O static characteristics
Table 35. I/O static characteristics



 同様に NRSTのリセットピンに内蔵プルアップ抵抗も標準で 40kΩなので同じ注意が必要かも?
 5.3.14 NRST pin characteristics
・Table 38. NRST pin characteristics
Table 38. NRST pin characteristics


RM0008 General-purpose and alternate-function I/Os (GPIOs and AFIOs)
 9.1 GPIO functional description
 PxODR register ・Table 20. Port bit configuration table
Table 20. Port bit configuration table



 9.5 GPIO and AFIO register maps
・Table 59. GPIO register map and reset values
Table 59. GPIO register map and reset values



GPIO electrical characteristics and definitions AN4899
 Each STM32 GPIO offers the possibility to select internal pull-up and pull-down (typical value = 40 kOhm)
・5.1.5 Pull-up calculation
5.1.5 Pull-up calculation




● STM32の GPIOの内蔵プルアップ抵抗の Arduinoのテストプログラム
#define USER_LED PC13
#define LED_OFF HIGH
#define LED_ON  LOW

#define USER_BUTTON PB12
#define BUTTON_OFF HIGH
#define BUTTON_ON  LOW

void setup() {
  pinMode(USER_LED, OUTPUT);
  pinMode(USER_BUTTON, INPUT_PULLUP);
}

void loop() {
  if (digitalRead(USER_BUTTON) == BUTTON_ON) {
    digitalWrite(USER_LED, LED_ON);
    delay(5);
    digitalWrite(USER_LED, LED_OFF);
    delay(100);
  }
}

● STM32CubeIDEで同様のプログラム
#define USER_LED_Pin GPIO_PIN_13
#define USER_LED_GPIO_Port GPIOC
#define USER_INPUT_Pin GPIO_PIN_12
#define USER_INPUT_GPIO_Port GPIOB

int main(void)
{
...

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    GPIO_PinState pinState = HAL_GPIO_ReadPin(USER_INPUT_GPIO_Port, USER_INPUT_Pin);

    if (pinState != GPIO_PIN_SET) {
      HAL_GPIO_WritePin(USER_LED_GPIO_Port, USER_LED_Pin, GPIO_PIN_RESET);
      HAL_Delay(5);
      HAL_GPIO_WritePin(USER_LED_GPIO_Port, USER_LED_Pin, GPIO_PIN_SET);
      HAL_Delay(100);

      continue;
    }
  }

...

}

static void MX_GPIO_Init(void)
{
...

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(USER_LED_GPIO_Port, USER_LED_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : USER_LED_Pin */
  GPIO_InitStruct.Pin = USER_LED_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(USER_LED_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : USER_INPUT_Pin */
  GPIO_InitStruct.Pin = USER_INPUT_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(USER_INPUT_GPIO_Port, &GPIO_InitStruct);

}


● STM32の GPIO関連のソースコード

STM32F1xx/Include/stm32f103x6.h
#define PERIPH_BASE      0x40000000UL /*!< Peripheral base address in the alias region */

#define APB2PERIPH_BASE  (PERIPH_BASE + 0x00010000UL)

#define GPIOA_BASE       (APB2PERIPH_BASE + 0x00000800UL)
#define GPIOB_BASE       (APB2PERIPH_BASE + 0x00000C00UL)
#define GPIOC_BASE       (APB2PERIPH_BASE + 0x00001000UL)
#define GPIOD_BASE       (APB2PERIPH_BASE + 0x00001400UL)

/**
  * @brief General Purpose I/O
  */
typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
} GPIO_TypeDef;

/******************  Bit definition for GPIO_BSRR register  *******************/
#define GPIO_BSRR_BS0_Pos     (0U)
#define GPIO_BSRR_BS0_Msk     (0x1UL << GPIO_BSRR_BS0_Pos)       /*!< 0x00000001 */
#define GPIO_BSRR_BS0         GPIO_BSRR_BS0_Msk                 /*!< Port x Set bit 0 */

...

#define GPIO_BSRR_BS15_Pos    (15U)
#define GPIO_BSRR_BS15_Msk    (0x1UL << GPIO_BSRR_BS15_Pos)      /*!< 0x00008000 */
#define GPIO_BSRR_BS15        GPIO_BSRR_BS15_Msk                /*!< Port x Set bit 15 */

g#define GPIO_BSRR_BR0_Pos     (16U)
#define GPIO_BSRR_BR0_Msk     (0x1UL << GPIO_BSRR_BR0_Pos)       /*!< 0x00010000 */
#define GPIO_BSRR_BR0         GPIO_BSRR_BR0_Msk                 /*!< Port x Reset bit 0 */

...

#define GPIO_BSRR_BR15_Pos    (31U)
#define GPIO_BSRR_BR15_Msk    (0x1UL << GPIO_BSRR_BR15_Pos)      /*!< 0x80000000 */
#define GPIO_BSRR_BR15        GPIO_BSRR_BR15_Msk                /*!< Port x Reset bit 15 */

STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c
void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)

STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c
  /* If we are configuring the pin in INPUT (also applicable to EVENT and IT mode) */
  case GPIO_MODE_INPUT:
  case GPIO_MODE_IT_RISING:
  case GPIO_MODE_IT_FALLING:
  case GPIO_MODE_IT_RISING_FALLING:
  case GPIO_MODE_EVT_RISING:
  case GPIO_MODE_EVT_FALLING:
  case GPIO_MODE_EVT_RISING_FALLING:
    /* Check the GPIO pull parameter */
    assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
    if (GPIO_Init->Pull == GPIO_NOPULL)
    {
      config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_FLOATING;
    }
    else if (GPIO_Init->Pull == GPIO_PULLUP)
    {
      config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD;

      /* Set the corresponding ODR bit */
      GPIOx->BSRR = ioposition;
    }
    else /* GPIO_PULLDOWN */
    {
      config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD;

      /* Reset the corresponding ODR bit */
      GPIOx->BRR = ioposition;
    }
    break;


● STM32 開発のヒント

開発のヒント - 周辺機能、I/O、メモリ - 未使用GPIOの処理

開発のヒント - 周辺機能、I/O、メモリ - GPIOの初期値



Tags: [ワンチップCPU]

●関連するコンテンツ(この記事を読んだ人は、次の記事も読んでいます)

STM32 STM32F103C8T6マイコンボードを ST-Link V2(中華製の互換ドングル)を使って開発
STM32 STM32F103C8T6マイコンボードを ST-Link V2(中華製の互換ドングル)を使って開発

  STM32F103C8 ARM Cortex-M3 72MHz CPU、ST-LINK Utilityでファームのアップデート

STM32 STM32F103C8T6の Windows用の開発環境を無料で構築する方法。CubeMX True STUDIO ST-LINK V2
STM32 STM32F103C8T6の Windows用の開発環境を無料で構築する方法。CubeMX True STUDIO ST-LINK V2

  Windows用の STM32F103C8 ARM Cortex-M3 72MHzの開発環境を無料で作る、STM32CubeMX、TrueSTUDIO、ST-LINK V2

STM32 STM32F103C8T6の USB CDC Virtual COM portドライバを Windows 7に組み込む方法
STM32 STM32F103C8T6の USB CDC Virtual COM portドライバを Windows 7に組み込む方法

  Windows 7で VCPドライバを組み込む時に「INFファイルが無効です」の解決方法、COMポート増殖を防ぐ方法(増えすぎた COMポートを削除)

STM32 STM32F103C8T6の USB CDC Virtual COM portデバイスを実装する
STM32 STM32F103C8T6の USB CDC Virtual COM portデバイスを実装する

  STM32 STM32F103C8T6に STCubeで CDC VCPデバイスを組み込み、動作試験のループバックを実装する

STM32 STM32F103C8T6で ARM GCCの Cソース中にインラインアセンブラを記述する方法
STM32 STM32F103C8T6で ARM GCCの Cソース中にインラインアセンブラを記述する方法

  ARM GCCの Cソース中にインラインアセンブラを記述する方法

STM32 STM32F103C8T6で SPI接続の 1.8インチ TFT液晶を使用する方法
STM32 STM32F103C8T6で SPI接続の 1.8インチ TFT液晶を使用する方法

  STM32に 128x160 ST7735 TFT 1.8インチ LCDを SPI接続して自前アプリから文字列を描画する方法。

STM32 STM32F103C8T6マイコンボード開発、CubeMX STM32CubeMXの使い方
STM32 STM32F103C8T6マイコンボード開発、CubeMX STM32CubeMXの使い方

  STM32マイコン用の初期設定コード生成ツール STM32CubeMXの使い方、USBデバイスの作成方法

STM32 STM32F103C8のクローン(複製品) 108MHz動作の GD32F103C8、CS32F103C8
STM32 STM32F103C8のクローン(複製品) 108MHz動作の GD32F103C8、CS32F103C8

  STM32クローン GigaDevice GD32F103C8T6 108MHz、CKS CS32F103C8T6 72MHz

ラズパイを意識した別物製品 Orange Pi Zeroを買ってみた、Allwinner H2+ Cortex-A7 4core
ラズパイを意識した別物製品 Orange Pi Zeroを買ってみた、Allwinner H2+ Cortex-A7 4core

  オレンジパイはラズパイよりもコスパは良いが情報が無いので利用者側に一定のスキルが必要

Orange Pi PC 2を買ってみた、Allwinner H5 Cortex-A53 4core ARM64
Orange Pi PC 2を買ってみた、Allwinner H5 Cortex-A53 4core ARM64

  ラズパイを意識した別物製品、オレンジパイはラズパイよりもコスパが良い、でも情報が無い

Raspberry Pi Zero Wを海外通販の Pimoroni等での購入方法、購入できる通販ショップ一覧まとめ
Raspberry Pi Zero Wを海外通販の Pimoroni等での購入方法、購入できる通販ショップ一覧まとめ

  ラズパイゼロW ワイヤレスモデルを海外通販でサクッと簡単に個人輸入で入手。技適通過でも国内販売は常に品切れ

大人気の CPUボード、Raspberry Pi 3 Model Bで作ってみよう
大人気の CPUボード、Raspberry Pi 3 Model Bで作ってみよう

  Raspberry Piの開発環境の構築やタッチパネル付き液晶ディスプレイや各種センサーの使い方まとめ

Espressif ESP32 Arduino互換でスケッチが使える WROOM32開発基板
Espressif ESP32 Arduino互換でスケッチが使える WROOM32開発基板

  Espressif ESP32 32ビット Arduino互換マイコンボードをお手軽に開発する方法

Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板
Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板

  Espressif ESP8266 ESP-12-E NodeMCU V1 ESP12 CP2102

BangGood通販はドローン以外にも面白い商品がまだまだ有った(電子工作編)
BangGood通販はドローン以外にも面白い商品がまだまだ有った(電子工作編)

  レーザー彫刻機、カラー液晶の DIYオシロ、Arduinoや Raspberry Pi用の小型カラー液晶




[HOME] | [BACK]
リンクフリー(連絡不要、ただしトップページ以外は Web構成の変更で移動する場合があります)
Copyright (c) 2023 FREE WING,Y.Sakamoto
Powered by 猫屋敷工房 & HTML Generator

http://www.neko.ne.jp/~freewing/cpu/stm32_gpio_pullup_very_weak/