記事のディレクトリ
1.GPIOの基本
質問:GPIOは何を指しますか?ピンが多いほど良いですか?
汎用入力出力汎用入力および出力インターフェース。実際、十分な数のピンで十分です。適切な数のチップを選択するだけです。
STM8マイクロコントローラーGPIOでサポートされるモード:
1.入力モードと特性
- フローティング入力/フローティング入力モード
特徴:
高い入力インピーダンス、アナログ信号がデジタル信号に変換される場合に適しており、ADCタイプでよく使用され、完全なアナログ信号特性を維持します
- プルアップ入力モード
特徴:
R1(30-80K、55Kが一般的な値)、ピンの不確実なレベル信号はプルアップ抵抗を介してハイレベルに渡され、抵抗は電流リミッタとしても機能します。
- その中で、Rが大きいほど、その効果は小さくなります。これは、弱いプルアップと呼ばれます。
- その中で、Rが小さいほど、その効果は大きくなります。これは、強力なプルアップと呼ばれます。
- 保護ダイオードの
特性:保護ダイオードの機能は、外部制御からの入力電圧が高すぎる(D1が降圧の役割を果たす)または低すぎる(D2がバリアダイオードは保護ダイオードとして機能します。
2.出力モードと特性
- プッシュプル/相補出力
機能:
2つのトランジスタまたはMOSトランジスタを使用します。プッシュプル出力はPP構造とも呼ばれ、伝導損失が低く、伝導損失が低く、効率が高くなっています。
- オープンドレイン出力
特徴:
決定する高レベル状態には外部プルアップ抵抗が必要です。このモードは電流タイプの駆動に適しており、その電流吸収能力は比較的強力です(通常20mA以内)。駆動電流の大部分は、プルアップ抵抗を介してピンに接続された回路またはデバイスへの外部電源によって供給され、マイクロコントローラ内に駆動電流を供給する必要はほとんどありません。そしてそれはラインとロジックを実現することができます。
- 真のオープンドレイン出力モード
特徴:
このピンの内部回路には、デジタル電源にプルアップされたPチャネルMOSチューブがなく、デジタル電源に接続された保護ダイオードもありません。内部回路は固定されており、このようなピンはプッシュプルモードで出力するように構成することはできません。
2.ピンの識別と構成
LQFPシンクワッドフラットパッケージ
- 説明記号の意味の説明
O1:低速出力、最大2MHz
O2:高速出力、最大10MHz
O3:プログラム可能な出力、リセット後の低速と一致
O4:プログラム可能な出力、リセット後の高速と一致
- チップピンの特性は
次のように分布しています。
- GPIO機能に関連して一般的に使用される5つのレジスタ。
各GPIOポートには、出力データレジスタ、入力データレジスタ、データ方向レジスタ、および2つの制御レジスタが割り当てられます。
- GPIOモード構成テーブルとモードステータス(データマニュアルを確認できます)
は、次の点に注意する必要があります。
- どの出力にもプルアップ抵抗はありません
- 入力には出力がないため、Pチャネルはありません
- 真のオープンドレインの場合、Pチャネルはなく、保護プルアップダイオードVddもありません。
第三に、構成レジスタのビット演算
(ビット単位または|、ビット単位および&、ビット単位の逆〜、左シフト>>、右シフト<<)
||は論理OR、&&は論理ANDであり、結果は01であり、ビットではないことに注意してください。操作。
- ビットOR演算、つまり、1演算を設定して、特定のビットを1に変更します。
例:
PB_DDR |= 0x44;
PB_DDR |= (0x1<<3);
- ビット演算、つまり、特定のビットを0に変更するためのクリア演算。
例:
PB_DDR &= 0x44;
PB_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++);
}
}
}