2.ランニングライトとボタンのGPIO構成とプログラミング

1.GPIOの基本

質問:GPIOは何を指しますか?ピンが多いほど良いですか?

汎用入力出力汎用入力および出力インターフェース。実際、十分な数のピンで十分です。適切な数のチップを選択するだけです。

STM8マイクロコントローラーGPIOでサポートされるモード:
ここに画像の説明を挿入

1.入力モードと特性

  1. フローティング入力/フローティング入力モード
    特徴:
    高い入力インピーダンス、アナログ信号がデジタル信号に変換される場合に適しており、ADCタイプでよく使用され、完全なアナログ信号特性を維持します
    ここに画像の説明を挿入
  2. プルアップ入力モード
    特徴:
    R1(30-80K、55Kが一般的な値)、ピンの不確実なレベル信号はプルアップ抵抗を介してハイレベルに渡され、抵抗は電流リミッタとしても機能します。
  • その中で、Rが大きいほど、その効果は小さくなります。これは、弱いプルアップと呼ばれます。
  • その中で、Rが小さいほど、その効果は大きくなります。これは、強力なプルアップと呼ばれます。
    ここに画像の説明を挿入
  1. 保護ダイオードの
    特性:保護ダイオードの機能は、外部制御からの入力電圧が高すぎる(D1が降圧の役割を果たす)または低すぎる(D2がバリアダイオードは保護ダイオードとして機能します。
    ここに画像の説明を挿入

2.出力モードと特性

  1. プッシュプル/相補出力
    機能:
    2つのトランジスタまたはMOSトランジスタを使用しますプッシュプル出力はPP構造とも呼ばれ、伝導損失が低く、伝導損失が低く、効率が高くなっています。
    ここに画像の説明を挿入
  2. オープンドレイン出力
    特徴:
    決定する高レベル状態には外部プルアップ抵抗が必要です。このモードは電流タイプの駆動に適しており、その電流吸収能力は比較的強力です(通常20mA以内)。駆動電流の大部分は、プルアップ抵抗を介してピンに接続された回路またはデバイスへの外部電源によって供給され、マイクロコントローラ内に駆動電流を供給する必要はほとんどありません。そしてそれはラインとロジックを実現することができます。
    ここに画像の説明を挿入
  3. 真のオープンドレイン出力モード
    特徴:
    このピンの内部回路には、デジタル電源にプルアップされたPチャネルMOSチューブがなく、デジタル電源に接続された保護ダイオードもありません。内部回路は固定されており、このようなピンはプッシュプルモードで出力するように構成することはできません。
    ここに画像の説明を挿入

2.ピンの識別と構成

LQFPシンクワッドフラットパッケージ
ここに画像の説明を挿入

  1. 説明記号の意味の説明
    ここに画像の説明を挿入
    O1:低速出力、最大2MHz
    O2:高速出力、最大10MHz
    O3:プログラム可能な出力、リセット後の低速と一致
    O4:プログラム可能な出力、リセット後の高速と一致
    ここに画像の説明を挿入
  2. チップピンの特性は
    ここに画像の説明を挿入
    次のように分布しています。
    ここに画像の説明を挿入
  3. GPIO機能に関連して一般的に使用される5つのレジスタ。
    各GPIOポートには、出力データレジスタ、入力データレジスタ、データ方向レジスタ、および2つの制御レジスタが割り当てられます。
    ここに画像の説明を挿入
  4. GPIOモード構成テーブルとモードステータス(データマニュアルを確認できます)
    ここに画像の説明を挿入
    は、次の点に注意する必要があります
  • どの出力にもプルアップ抵抗はありません
  • 入力には出力がないため、Pチャネルはありません
  • 真のオープンドレインの場合、Pチャネルはなく、保護プルアップダイオードVddもありません。

第三に、構成レジスタのビット演算

(ビット単位または|、ビット単位および&、ビット単位の逆〜、左シフト>>、右シフト<<)
||は論理OR、&&は論理ANDであり、結果は01であり、ビットではないことに注意しください。操作。

  • ビットOR演算、つまり、1演算を設定して、特定のビットを1に変更します。
    例:
PB_DDR |= 0x44PB_DDR |= (0x1<<3)
  • ビット演算、つまり、特定のビットを0に変更するためのクリア演算。
    例:
PB_DDR &= 0x44PB_DDR &= ~(0x1<<3)
  • 値の操作、ポートステータスを読み取り、それを変数「x」に割り当てます。
    例:
x = (PB_IDR >> 2) & 0x01;		//读取PB2端口状态
  • PBグループポートの上位4ビットを2MHzスロープオープンドレイン出力モードに設定し、下位4ビットを10MHzスロープレイト出力モードに設定して、ポートが「01010111」レベルのステータスを出力できるようにします。
PB_DDR = 0xFF;
PB_CR1 = 0x0F;
PB_CR2 = 0x0F;
PB_ODR = 0x57

その中で、IARは5000行以上のヘッダーファイルを書いているので、関連するビットの直接操作をサポートできます。これはより便利ですが、STVDはそれをサポートしていません。つまり、2つのソフトウェアコードは移植時に変更されます。IARヘッダーファイルによってもたらされるトラバーサル:

/*---------------------------------------------------------
 *      Port B bit fields
 *-------------------------------------------------------*/
#ifdef __IAR_SYSTEMS_ICC__

#define PB_ODR_ODR0              PB_ODR_bit.ODR0
#define PB_ODR_ODR1              PB_ODR_bit.ODR1
#define PB_ODR_ODR2              PB_ODR_bit.ODR2
#define PB_ODR_ODR3              PB_ODR_bit.ODR3
#define PB_ODR_ODR4              PB_ODR_bit.ODR4
#define PB_ODR_ODR5              PB_ODR_bit.ODR5
#define PB_ODR_ODR6              PB_ODR_bit.ODR6
#define PB_ODR_ODR7              PB_ODR_bit.ODR7

#define PB_IDR_IDR0              PB_IDR_bit.IDR0
#define PB_IDR_IDR1              PB_IDR_bit.IDR1
#define PB_IDR_IDR2              PB_IDR_bit.IDR2
#define PB_IDR_IDR3              PB_IDR_bit.IDR3
#define PB_IDR_IDR4              PB_IDR_bit.IDR4
#define PB_IDR_IDR5              PB_IDR_bit.IDR5
#define PB_IDR_IDR6              PB_IDR_bit.IDR6
#define PB_IDR_IDR7              PB_IDR_bit.IDR7

#define PB_DDR_DDR0              PB_DDR_bit.DDR0
#define PB_DDR_DDR1              PB_DDR_bit.DDR1
#define PB_DDR_DDR2              PB_DDR_bit.DDR2
#define PB_DDR_DDR3              PB_DDR_bit.DDR3
#define PB_DDR_DDR4              PB_DDR_bit.DDR4
#define PB_DDR_DDR5              PB_DDR_bit.DDR5
#define PB_DDR_DDR6              PB_DDR_bit.DDR6
#define PB_DDR_DDR7              PB_DDR_bit.DDR7

#define PB_CR1_C10               PB_CR1_bit.C10
#define PB_CR1_C11               PB_CR1_bit.C11
#define PB_CR1_C12               PB_CR1_bit.C12
#define PB_CR1_C13               PB_CR1_bit.C13
#define PB_CR1_C14               PB_CR1_bit.C14
#define PB_CR1_C15               PB_CR1_bit.C15
#define PB_CR1_C16               PB_CR1_bit.C16
#define PB_CR1_C17               PB_CR1_bit.C17

#define PB_CR2_C20               PB_CR2_bit.C20
#define PB_CR2_C21               PB_CR2_bit.C21
#define PB_CR2_C22               PB_CR2_bit.C22
#define PB_CR2_C23               PB_CR2_bit.C23
#define PB_CR2_C24               PB_CR2_bit.C24
#define PB_CR2_C25               PB_CR2_bit.C25
#define PB_CR2_C26               PB_CR2_bit.C26
#define PB_CR2_C27               PB_CR2_bit.C27

#endif

具体操作:
ここに画像の説明を挿入

4つ、流水ライトとボタン

1.ウォーターランプを左に動かします

void LED_Left_Play2(void)
{
  u8 x = 0xFE;
  u8 i = 0;
  for(i = 0; i <4; i++){
    PI_ODR = x;
    delay_ms(20);
    x = x << 1;
    x |= 0x01;
  }
}

2.ウォーターランプを右に動かします

void LED_Right_Play2(void)
{
  u8 x = 0xF7;
  u8 i = 0;
  for(i = 0; i < 4; i++){
    PI_ODR = x;
    delay_ms(20);
    x = x >> 1;
    x |= 0x80;
  }
}

3.前後にループします

void LED_Left_Play(void)   //左移流水灯     
{
  PI_ODR_ODR0 = 0;
  PI_ODR_ODR3 = 1;
  delay_ms(20);
  PI_ODR_ODR1 = 0;
  PI_ODR_ODR0 = 1;
  delay_ms(20);
  PI_ODR_ODR2 = 0;
  PI_ODR_ODR1 = 1;
  delay_ms(20);
  PI_ODR_ODR3 = 0;
  PI_ODR_ODR2 = 1;
}

void LED_Right_Play(void)      //右移流水灯
{
  PI_ODR_ODR3 = 0;
  PI_ODR_ODR0 = 1;
  delay_ms(20);
  PI_ODR_ODR2 = 0;
  PI_ODR_ODR3 = 1;
  delay_ms(20);
  PI_ODR_ODR1 = 0;
  PI_ODR_ODR2 = 1;
  delay_ms(20);
  PI_ODR_ODR0 = 0;
  PI_ODR_ODR1 = 1;
}

4.流水ランプアレイの設計

void LED_MyDesign(void)
{
  u8 MyLed[8] = {0xFE,0xF7,0xFE,0xF7,0xFD,0xFB,0xFD,0xFB};
  u8 MyLed2[8] = {0xF6,0xF9,0xF6,0xF9,0xFA,0xF5,0xFA,0xF5};
  u8 MyLed3[9]={0xF6,0xF9,0xF6,0xF9,0xFF,0xF0,0xFF,0xF0,0xFF};
  u8 i;
   for(i = 0; i < 9; i++){
    PI_ODR = MyLed3[i];
    delay_ms(20);
  }
  for(i = 0; i < 8; i++){
    PI_ODR = MyLed[i];
    delay_ms(20);
  }
  for(i = 0; i < 8; i++){
    PI_ODR = MyLed2[i];
    delay_ms(20);
  }
}

5.ボタンコントロールLEDライト

#define KEY8 PA_IDR_IDR1        //输入量
#define LED0 PI_ODR_ODR0        //输出量
void Key_For_Led(void)  //PA1控制K8
{
    //键盘按键控制LED灯,PA1控制LED0
  PI_DDR_DDR0 = 1;
  PI_CR1_C10 = 1;
  PI_CR2_C20 = 0;
  LED0 = 1;      //熄灭
  
  PA_DDR_DDR1 = 0;
  PA_CR1_C11 = 1; 
  PA_CR2_C21 = 0;
  
while(1){
    if(KEY == 0){  //按键按下
      delay_ms(5);  //消抖
      if(KEY == 0){//再次确认按键按下
        LED = !LED;   //控制LED灯
      }
    while(!KEY);        //如果一直处于按下则等待,很关键,需等待到按键松开再启动新一轮的循环
    }
    // while(!KEY);    //错误的地方,应该为按键按下的时间段中,所以应该包含在if语句中
  }
}

void delay_ms(u32 time)
{
  u32 i,j;
  while(time--){
    for(i = 0; i < 10; i++){
      for(j = 0; j < 100; j++);
    }
  }
}

6.トータルコードをデバッグします

#include "iostm8s208mb.h"

#define u8  uint8_t
#define u16 uint16_t
#define u32 uint32_t
typedef unsigned char    uint8_t;
typedef unsigned short   uint16_t;
typedef unsigned long    uint32_t;

#define KEY8 PB_IDR_IDR1        //输入量
#define LED0 PI_ODR_ODR0        //输出量

void Key_For_Led(void);     
void GPIO_Init(void);
void LED_light(void);
void LED_Right_Play(void);
void LED_Left_Play(void);
void LED_Right_Play2(void);
void LED_Left_Play2(void);
void LED_MyDesign(void);
void delay_ms(u16 time);

u32 count ;

int main()
{
  //GPIO_Init();
  
  /*    闪烁灯
  PI_ODR_ODR2 = 0;
  PI_ODR_ODR1 = 0;
  while(count--){
    LED_light();
  }
  */
  
 /*   花样流水灯
  while(1)
    LED_MyDesign();
  
  count = 3;
  while(count--)
    LED_Right_Play2();
 
 count = 3;
  while(count--)
    LED_Left_Play2();
  
  count = 3;
  while(count--){     //来回移动
    LED_Left_Play();
    LED_Right_Play();
  }
  */
  
    Key_For_Led();
  
}

void GPIO_Init(void)    //GPIO初始化
{
  /*
  PI_DDR_DDR2 = 1;
  PI_CR1_C12 = 1;
  PI_CR2_C22 = 0;

  PI_DDR_DDR1 = 1;
  PI_CR1_C11 = 1;
  PI_CR2_C21 = 0;
  
  PI_DDR |= 0x09;
  PI_CR1 |= 0x09;
  PI_CR2 &= 0xF6;
  */
  
  PI_DDR |= 0x0F;
  PI_CR1 |= 0x0F;
  PI_CR2 &= 0xF0;
  PI_ODR |= 0x0F;
  
  
  
}

void Key_For_Led(void)  //PA1控制K8
{
    //键盘按键控制LED灯,PA1控制LED0
  PI_DDR_DDR0 = 1;
  PI_CR1_C10 = 1;
  PI_CR2_C20 = 0;
  LED0 = 1;      //熄灭
  
  PB_DDR_DDR1 = 0;
  PB_CR1_C11 = 1;
  PB_CR2_C21 = 0;
  
while(1){
    if(KEY == 0){  //按键按下
      delay_ms(5);  //消抖
      if(KEY == 0){//再次确认按键按下
        LED = !LED;   //控制LED灯
      }
    while(!KEY);        //如果一直处于按下则等待
    }
  }
   
}


void LED_MyDesign(void)
{
  u8 MyLed[8] = {0xFE,0xF7,0xFE,0xF7,0xFD,0xFB,0xFD,0xFB};
  u8 MyLed2[8] = {0xF6,0xF9,0xF6,0xF9,0xFA,0xF5,0xFA,0xF5};
  u8 MyLed3[9]={0xF6,0xF9,0xF6,0xF9,0xFF,0xF0,0xFF,0xF0,0xFF};
  u8 i;
   for(i = 0; i < 9; i++){
    PI_ODR = MyLed3[i];
    delay_ms(20);
  }
  for(i = 0; i < 8; i++){
    PI_ODR = MyLed[i];
    delay_ms(20);
  }
  for(i = 0; i < 8; i++){
    PI_ODR = MyLed2[i];
    delay_ms(20);
  }
}

void LED_light(void)    //闪烁灯
{
  PI_ODR &= 0xF6;
  delay_ms(20);
  PI_ODR |= 0x09;
  delay_ms(20);
}

void LED_Right_Play2(void)
{
  u8 x = 0xF7;
  u8 i = 0;
  for(i = 0; i < 4; i++){
    PI_ODR = x;
    delay_ms(20);
    x = x >> 1;
    x |= 0x80;
  }
}

void LED_Left_Play2(void)
{
  u8 x = 0xFE;
  u8 i = 0;
  for(i = 0; i <4; i++){
    PI_ODR = x;
    delay_ms(20);
    x = x << 1;
    x |= 0x01;
  }
}

void LED_Left_Play(void)   //左移流水灯     
{
  PI_ODR_ODR0 = 0;
  PI_ODR_ODR3 = 1;
  delay_ms(20);
  PI_ODR_ODR1 = 0;
  PI_ODR_ODR0 = 1;
  delay_ms(20);
  PI_ODR_ODR2 = 0;
  PI_ODR_ODR1 = 1;
  delay_ms(20);
  PI_ODR_ODR3 = 0;
  PI_ODR_ODR2 = 1;
}

void LED_Right_Play(void)      //右移流水灯
{
  PI_ODR_ODR3 = 0;
  PI_ODR_ODR0 = 1;
  delay_ms(20);
  PI_ODR_ODR2 = 0;
  PI_ODR_ODR3 = 1;
  delay_ms(20);
  PI_ODR_ODR1 = 0;
  PI_ODR_ODR2 = 1;
  delay_ms(20);
  PI_ODR_ODR0 = 0;
  PI_ODR_ODR1 = 1;
}

void delay_ms(u16 time)
{
  u8 i,j;
  while(time--){
    for(i = 0; i < 50; i++){
      for(j = 0; j < 20; j++);
    }
  }
}






おすすめ

転載: blog.csdn.net/weixin_44751294/article/details/106654800