Article Directory
1. GPIO basics
Question: What does GPIO refer to? Is the more pins the better?
General Purpose Input Output General purpose input and output interface; in fact, enough pins are good enough, just choose a suitable number of chips.
Modes supported by STM8 microcontroller GPIO:
1. Input mode and characteristics
- Floating input/floating input mode
Features:
high input impedance, suitable for occasions where analog signals are converted to digital signals, often used in ADC types, maintaining complete analog signal characteristics
- Pull-up input mode
Features:
R1 (30-80K, 55K is a common value), the uncertain level signal on the pin is passed to a high level through a pull-up resistor, and the resistor also acts as a current limiter.
- Among them, the larger R is, the smaller its effect is, which is called weak pull-up;
- Among them, the smaller R is, the greater its effect is, which is called strong pull-up;
- Protection diode
characteristics: The function of the protection diode is to place a germanium diode or Schottky with a lower voltage drop if the input voltage from the external control is too high (D1 plays a role in stepping down) or too low (D2 plays a role in adjusting close to 0V). The barrier diode serves as a protection diode.
2. Output mode and characteristics
- Push-pull/complementary output
Features:
Use two transistors or MOS transistors. Push-pull output is also referred to as PP structure, with low conduction loss, low conduction loss and high efficiency.
- Open-drain output
Features:
The high-level state to be determined requires an external pull-up resistor. This mode is suitable for current-type driving, and its current absorption capability is relatively strong (generally within 20mA). Most of the drive current is provided by the external power supply to the circuit or device connected to the pin through a pull-up resistor, and there is almost no need to provide a drive current inside the microcontroller. And it can realize line-and logic.
- True open-drain output mode
Features:
There is no P-channel MOS tube pulled up to the digital power supply in the internal circuit of this pin, and there is no protection diode connected to the digital power supply. The internal circuit is fixed, such pins cannot be configured to output in push-pull mode.
2. Pin identification and configuration
LQFP Thin Quad Flat Package
- Explanation of the meaning of the description symbols
O1: Slow output, up to 2MHz
O2: Fast output, up to 10MHz
O3: Programmable output, consistent with slow speed after reset
O4: Programmable output, consistent with fast after reset
- The chip pin characteristics are
distributed as follows:
- Five commonly used registers related to GPIO functions.
Each GPIO port is allocated: an output data register, an input data register, a data direction register and two control registers.
- GPIO mode configuration table and mode status (you can check the data manual)
need to pay attention to:
- None of the outputs have pull-up resistors
- The input has no output, so there is no P channel
- For true open drain, there is no P-channel, and there is no protective pull-up diode Vdd.
Third, the bit operation of the configuration register
(Bitwise or |, bitwise and &, bitwise inverse ~, left shift >>, right shift <<) It
should be noted that || is a logical OR, && is a logical AND, the result is only 01, not a bit operation.
- Bit-OR operation, that is, set 1 operation to change a certain bit into 1
eg:
PB_DDR |= 0x44;
PB_DDR |= (0x1<<3);
- Bit-and operation, that is, clearing operation to change a certain bit to 0
eg:
PB_DDR &= 0x44;
PB_DDR &= ~(0x1<<3);
- Value operation, read the port status and assign it to the variable "x"
eg:
x = (PB_IDR >> 2) & 0x01; //读取PB2端口状态
- Configure the high 4 bits of the PB group port for 2MHz slope open-drain output mode, and the low four bits for 10MHz slope late output mode, allowing the port to output "01010111" level status
PB_DDR = 0xFF;
PB_CR1 = 0x0F;
PB_CR2 = 0x0F;
PB_ODR = 0x57
Among them, because IAR has written a header file of more than five thousand lines for us, it can support direct manipulation of the relevant bits, which is more convenient, but STVD does not support it, that is, the two software codes need to be changed when transplanting. Traversal brought by IAR header files:
/*---------------------------------------------------------
* 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
Specific operation:
Four, running water lights and buttons
1. Move the water lamp to the left
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. Move the water lamp to the right
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 back and forth
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. Design of running water lamp array
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. Button control Led light
#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. Debug the total code
#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++);
}
}
}