2. Configuração GPIO e programação de luzes de corrida e botões

1. Noções básicas de GPIO

Pergunta: O que GPIO se refere? Quanto mais alfinetes, melhor?

Entrada e saída de uso geral Interface de entrada e saída de uso geral; na verdade, pinos suficientes são bons o suficiente, basta escolher um número adequado de chips.

Modos suportados pelo microcontrolador STM8 GPIO:
Insira a descrição da imagem aqui

1. Modo de entrada e características


  1. Características do modo de entrada flutuante / entrada flutuante :
    alta impedância de entrada, adequada para ocasiões em que os sinais analógicos são convertidos em sinais digitais, frequentemente usados ​​em tipos de ADC, mantendo características completas do sinal analógico
    Insira a descrição da imagem aqui

  2. Recursos do modo de entrada pull-up :
    R1 (30-80K, 55K é um valor comum), o sinal de nível incerto no pino é passado para um nível alto por meio de um resistor pull-up e o resistor também atua como um limitador de corrente.
  • Entre eles, quanto maior for o R, menor será o seu efeito, o que é denominado pull-up fraco;
  • Entre eles, quanto menor for o R, maior será o seu efeito, o que se denomina pull-up forte;
    Insira a descrição da imagem aqui

  1. Características do diodo de proteção : A função do diodo de proteção é colocar um diodo de germânio ou Schottky com uma queda de tensão mais baixa se a tensão de entrada do controle externo for muito alta (D1 desempenha um papel na redução) ou muito baixa (D2 desempenha um papel no ajuste próximo a 0 V. O diodo de barreira serve como um diodo de proteção.
    Insira a descrição da imagem aqui

2. Modo de saída e características


  1. Recursos de saída push-pull / complementar :
    Use dois transistores ou transistores MOS. A saída push-pull também é conhecida como estrutura PP, com baixa perda de condução, baixa perda de condução e alta eficiência.
    Insira a descrição da imagem aqui

  2. Recursos de saída de dreno aberto :
    O estado de alto nível a ser determinado requer um resistor pull-up externo.Este modo é adequado para acionamento do tipo de corrente e sua capacidade de absorção de corrente é relativamente forte (geralmente dentro de 20mA). A maior parte da corrente de acionamento é fornecida pela fonte de alimentação externa ao circuito ou dispositivo conectado ao pino por meio de um resistor pull-up e quase não há necessidade de fornecer uma corrente de acionamento dentro do microcontrolador. E pode realizar linha e lógica.
    Insira a descrição da imagem aqui

  3. Características do modo de saída de dreno aberto verdadeiro :
    Não há tubo MOS de canal P puxado para a fonte de alimentação digital no circuito interno deste pino e não há diodo de proteção conectado à fonte de alimentação digital. O circuito interno é fixo, tais pinos não podem ser configurados para saída no modo push-pull.
    Insira a descrição da imagem aqui

2. Identificação e configuração do pino

Pacote LQFP Thin Quad Flat
Insira a descrição da imagem aqui

  1. Explicação do significado dos símbolos de descrição
    Insira a descrição da imagem aqui
    O1: Saída lenta, até 2 MHz
    O2: Saída rápida, até 10 MHz
    O3: Saída programável, consistente com velocidade lenta após a reinicialização
    O4: Saída programável, consistente com rápida após a reinicialização
    Insira a descrição da imagem aqui
  2. As características do pino do chip são
    Insira a descrição da imagem aqui
    distribuídas da seguinte forma:
    Insira a descrição da imagem aqui
  3. Cinco registros comumente usados ​​relacionados às funções
    GPIO.Cada porta GPIO é alocada: um registro de dados de saída, um registro de dados de entrada, um registro de direção de dados e dois registros de controle.
    Insira a descrição da imagem aqui
  4. A tabela de configuração do modo GPIO e o status do modo (você pode verificar o manual de dados)
    Insira a descrição da imagem aqui
    precisam prestar atenção a:
  • Nenhuma das saídas tem resistores pull-up
  • A entrada não tem saída, então não há canal P
  • Para um dreno verdadeiramente aberto, não há canal P e não há diodo de proteção pull-up Vdd.

Terceiro, a operação de bits do registro de configuração

(Bit a bit ou |, bit a bit e &, bit a bit inverso ~, deslocamento para a esquerda >>, deslocamento para a direita <<)
Deve-se notar que || é um OR lógico, && é um AND lógico, o resultado é apenas 01, não um bit Operação.

  • Operação bit-OR, ou seja, definir 1 operação para alterar um determinado bit em 1,
    por exemplo:
PB_DDR |= 0x44PB_DDR |= (0x1<<3)
  • Bit-and operation, ou seja, operação de limpeza para alterar um determinado bit para 0,
    por exemplo:
PB_DDR &= 0x44PB_DDR &= ~(0x1<<3)
  • Valor da operação, leia o status da porta e atribua-o à variável "x",
    por exemplo:
x = (PB_IDR >> 2) & 0x01;		//读取PB2端口状态
  • Configure os 4 bits altos da porta do grupo PB para o modo de saída de dreno aberto de inclinação de 2 MHz e os quatro bits baixos para o modo de saída tardia de inclinação de 10 MHz, permitindo que a porta envie o status de nível "01010111"
PB_DDR = 0xFF;
PB_CR1 = 0x0F;
PB_CR2 = 0x0F;
PB_ODR = 0x57

Entre eles, como o IAR escreveu um arquivo de cabeçalho com mais de cinco mil linhas para nós, ele pode suportar a manipulação direta dos bits relevantes, o que é mais conveniente, mas o STVD não o suporta, ou seja, os dois códigos de software precisam ser alterado durante o transplante. Traversal trazido por arquivos de cabeçalho 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

Operação específica:
Insira a descrição da imagem aqui

Quatro, luzes e botões de água corrente

1. Mova a lâmpada de água para a esquerda

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. Mova a lâmpada de água para a direita

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. Loop para frente e para trás

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. Projeto de conjunto de lâmpadas de água corrente

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. Botão de controle de luz 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. Depure o código total

#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++);
    }
  }
}






Acho que você gosta

Origin blog.csdn.net/weixin_44751294/article/details/106654800
Recomendado
Clasificación