Recently I am using STM8S003F to simulate the serial port to send data. There are many resources on the Internet, but I didn’t find what I needed. So I wrote an article and made a summary. This article mainly implements the simple sending process without using library functions.
1. Principles of serial port communication and principles of simulating serial port data transmission
The standard serial port data format is: start bit (1 bit) + data bit (8 bits) + check bit (1 bit) + stop bit (1 bit). The start bit is low level and the stop bit is high level.
Serial communication requires setting the baud rate and checking the COM port.
The idea is this: we use timer TIM2 to send a bit every other time, thereby simulating the serial port to send data.
2. Get the value of timer ARR automatically loaded
For simplicity, we don't use the check bit, so there are 10 bits of data in total.
I take the process of calculating the baud rate of 9600bit/s in stm8 as an example (9600 bits are transmitted in 1 second).
It can be calculated that the time required to transmit 1 bit is T1 = 1/9600, which is approximately 104us.
The internal crystal frequency of stm8 is 16M. I use 16 division, which is 1M, so the MCU oscillation period is 1/1M = 1us.
From the above calculation, we know that to send one bit of data, the value of the automatic load in the timer should be set to 104/1 = 104.
3. Implementation process
During the implementation process, we divided the project folder SimUART into 4 folders (System: for storing system files; Project: for storing project files; User: for storing main.c and UserApp.c; My_Lib: for storing other commonly used files). According to the resources of the microcontroller we will use, we divided three files in My_Lib, namely - Delay: for storing files related to delay functions; IO: for storing files related to IO port functions; Time: for files related to timer functions. Below I paste the .c files of the relevant functions, and the .h files are omitted. Students in need can download and use them according to the URL at the end of the article. My programming environment is IAR, and I need to create an IAR project myself. MARK, which will be introduced later. The following is a detailed introduction (Project and System are omitted, and System only uses stm8s.h).
3.1. Everything starts from main.c
First, in main.c, we need to initialize the resources of the MCU. We write it in the All_Config() function [in UserApp.c], the code is as follows:
//head file
#include "UserApp.h"
#include "IO.h"
#include "User.h"
#include "Time.h"
// Initialization function
void All_Config( void )
{
Clock_Config();
IO_Init();
TIM2_Heat();
}
Among them, User.h is a file in which I write my commonly used macros, corresponding to main.c.
When no external clock is connected, the main clock of STM8S003F defaults to 8-frequency division of HSI RC clock at startup. The initialization here only specifies 16MHZ high-speed internal RC oscillator (HSI), which can also be omitted. The function code of Clock_Config() [in UserApp.c] is as follows:
// Initialize the clock to select the internal 16M crystal oscillator
void Clock_Config()
{
CLK->CKDIVR &= ~( BIT(4) | BIT(3) );
}
I choose PD2 of the microcontroller as the data transmission port of my simulated serial port. The IO_Init() function code in IO.c is as follows:
//head file
#include "IO.h"
#include "User.h"
void IO_Init()
{
//TXD: TXD bit push-pull output PD2
UART_PORT->ODR |= UART_PIN_TX; //0000 0000
UART_PORT->DDR |= UART_PIN_TX; //0000 1000
UART_PORT->CR1 |= UART_PIN_TX; //0000 1000
UART_PORT->ODR &= ~UART_PIN_TX;
UART_PORT->ODR |= UART_PIN_TX;
}
The macro definition in IO.h is:
#define UART_PORT GPIOD
#define UART_PIN_TX 0X04 // PD2
#define UART_PIN_RX 0X08 // PD3
The following is the initialization of the timer. When using the timer, we divide it into the following steps:
a. Select the timer, we choose TIM2;
b. The clock division of the timer (pay attention to whether it is the default 8-division or has been changed). I did not have a division at the beginning and needed a 16-division.
c. Fill in the value that the timer automatically loads, in my case it is 104;
d. Start the timer;
Note that the counter CNTR is automatically reset to 0 when powered on. We still need to clear it to zero. After using the auto-reload register, the auto-reload register determines the overflow timing of the timer. When the value in the timer counter reaches the value specified by the auto-reload register, the counter will be reset to zero. In other words, the auto-reload register determines the period of the timer.
In the method of simulating serial port data transmission introduced in this article, no interrupt is used. The function code of TIM2_Init() [in TIM2.c] is as follows:
//head file
#include "TIM2.h"
#include "User.h"
void TIM2_Init()
{
CLK->PCKENR1 |= CLK_PCKENR1_TIM2; //TIM2 enable
TIM2->PSCR = 0x04; //16-division 1MHZ 1us
TIM2->ARRH = 104 >> 8; //Automatically load and reset TIM2 every 52us
TIM2->ARRL = 104; //Decrease by 1 every 1us
TIM2->CNTRH = 0;TIM2->CNTRL = 0;
TIM2->CR1 |= TIM2_CR1_CEN; //Start the timer}
After completing the initialization, we should write the sending program. For simple sending, we choose to send 0x55 because it shows a square wave in the oscilloscope. We write our implementation of our simulated serial port sending in UserApp.c.
The rules for sending data are:
a. There are 10 bits of data in total (so 16 bits of data are needed, 8 bits are not enough). Since the data we send is 8 bits, there is a conversion process;
b. Send low digits first, then high digits;
c. There is a time delay code in the sending function to ensure that every data is a counting time (that is, a 104 count is completed)
The code of the sending function SimUART_TxByte() [in UserApp.c] is as follows
void SimUART_TxByte( u8 SendData )
{
static u16 Send_All = 0;
static u8 BitNum = 0; //bit count
Send_All = SendData;
Send_All = ( Send_All << 1 ) | 0X0200; //10 bits of data to be sent
TIM2->CNTRH = 0;
TIM2->CNTRL = 0;
TIM2->SR1 &= ~TIM2_SR1_UIF;
//Send low bit first, then high bit
for( BitNum = 0; BitNum<10 ; BitNum++ )
{
if( Send_All & 0X0001 ) //If it is a high level, send a high level
{
UART_PORT->ODR |= UART_PIN_TX;
}
else //If it is a low level, send a low level
{
UART_PORT->ODR &= ~UART_PIN_TX;
}
Send_All >>= 1; //Move right one bit
//Wait for baud rate time
while( (TIM2->SR1 & TIM2_SR1_UIF) == 0 );
TIM2->SR1 &= ~TIM2_SR1_UIF;
}
}
Among them, UART_PIN_TX is the macro definition in IO.c.
3.2. Complete the main() function
After completing the above code, we can test it. Now let's complete the main() function. The code is as follows:
//head file
#include "User.h"
#include "UserApp.h"
#include "Delay.h"
int main( void )
{
char Test = 0;
//char Test = 0x55; //test data
All_Config(); // Initialization
while(1) //Send loop
{
SimUART_TxByte( Test++ );
Delay_50000(); //Delay to prevent excessive data
}
//return 0;
}
After 0x55 is sent correctly, we send 0x00 to 0xFF. If the baud rate is incorrect, the transmission will be discontinuous. In order to prevent too much data, we need a delay function. The function code of Delay_50000() [IO.C] is as follows:
//Head file
#include "Delay.h"
void Delay_50000()
{
int a,b;
for( a=0 ; a<100 ; a++ )
{
for( b=0 ; b<500 ; b++ );
}
}
4 Conclusion
So far, we have realized the function of using the IO port to simulate the serial port (without using the library function) to send data. The relevant code can be downloaded and used at the following address. Everyone is welcome to learn and communicate with me.
Previous article:STM8S MCU serial port debugging
Next article:Usage of UART in stm8s (four types of UART interrupts)
Recommended ReadingLatest update time:2024-11-16 10:52
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Introduction to 5G Small Cells
- 【GD32L233C-START Review】Three Power Consumption
- Which wireless method is the fastest for transferring files between mobile phones and computers?
- ZTE Hardware Written Test
- SMD Photoelectric Sensor Applications
- Finally, we've got you! TI.com's online purchasing platform has been fully upgraded, with free shipping nationwide and delivery in as fast as 2 days
- Live Review: ADI Motor Control Solutions on October 12
- MSP430AFE2xx series of metering analog front-end 16-bit MCU
- Integer overflow problem occurs when using AD10
- Chapter 7 UART Usage - Polling and Interrupt Mode