Artigo Diretório
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:
1. Modo de entrada e características
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
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;
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.
2. Modo de saída e características
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.
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.
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.
2. Identificação e configuração do pino
Pacote LQFP Thin Quad Flat
- Explicação do significado dos símbolos de descrição
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
- As características do pino do chip são
distribuídas da seguinte forma:
- 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.
- A tabela de configuração do modo GPIO e o status do modo (você pode verificar o manual de dados)
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 |= 0x44;
PB_DDR |= (0x1<<3);
- Bit-and operation, ou seja, operação de limpeza para alterar um determinado bit para 0,
por exemplo:
PB_DDR &= 0x44;
PB_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:
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++);
}
}
}