// UART.C
// General simulation serial port program
// Resource requirements: one hardware counter, two I/O ports
// Set the hardware counter's count time to three times the baud rate
// Define two I/O ports for sending and receiving, used in receive() and transmit(char) respectively
// Set up a dedicated receive buffer to store received data
// Note: The timer must be set according to the baud rate;
// Each time communication starts, the initialization function init_uart() must be called
//------------------------------------------------ -------------------------------------------------- ---------------
//----------------------------------Pin definition, library function declaration-------------------------------------------------
#include
#include
//Port definition
sbit RXD3=P1^0;
sbit TXD3=P1^1;
//----------------------------------------------Variable declaration-----------------------------------------------------
#define IN_BUF_SIZE 10 //Input buffer length definition
#define TRUE 1
#define FALSE 0
static unsigned char inbuf[IN_BUF_SIZE]; //input buffer
static unsigned char qin = 0;
static unsigned char qout = 0;
static char flag_rx_waiting_for_stop_bit;
static char flag_rx_off;
static char rx_mask;
static char flag_rx_ready;
static char flag_tx_ready;
static char timer_rx_ctr;
static char timer_tx_ctr;
static char bits_left_in_rx;
static char bits_left_in_tx;
static char rx_num_of_bits;
static char tx_num_of_bits;
static char internal_rx_buffer;
static char internal_tx_buffer;
static char user_tx_buffer;
//----------------------------------Hardware related function declarations------------------------------------------------
bit get_rx_pin_status(); //1. Returns the value returned by the receive pin (0 or 1)
void set_tx_pin_high(void); //2. Set the transmit pin high, output 1
void set_tx_pin_low(); //3. Set the transmit pin to low, output 0
void timer_set(); //4. Set the timer value to three times the baud rate
void set_timer_interrupt(); //5. Enable timer interrupt
void idle(); //6. Execute while waiting for port input, modify according to specific application
//-----------------------------------Declare hardware-independent functions-------------------------------------------
void flush_input_buffer( void ); // Clear the receive buffer
char kbhit( void ); // Determine whether the data is received normally
char get_char( void ); // Read a data from the receive buffer
void turn_rx_on( void ); // Start receiving function
void turn_rx_off( void ); // End receiving function
extern void put_char( char ); // Send a data to the sender.
void timer_isr(void); //interrupt processing function
//------------------------------------------------ -------------------------------------------------- -----
// Function name: set_tx_pin_high
// Function description: Set the serial port sending port to high, which is related to the hardware
//------------------------------------------------ -------------------------------------------------- ------
void set_tx_pin_high( void )
{
TXD3=1;
}
//------------------------------------------------ -------------------------------------------------- -----
// Function name: set_tx_pin_low
// Function description: Set the serial port sending port to low, which is related to the hardware
//------------------------------------------------ -------------------------------------------------- ------
void set_tx_pin_low( void )
{
TXD3=0;
}
//------------------------------------------------ -------------------------------------------------- -----
// Function name: get_rx_pin_status
// Function description: Returns the status of the receiving port, high is 1, low is 0, related to the hardware
//------------------------------------------------ -------------------------------------------------- ------
bit get_rx_pin_status()
{
return(RXD3);
}
//------------------------------------------------ -------------------------------------------------- -----
// Function name: timer_set
// Function description: Set the timer working status, related to the hardware
//------------------------------------------------ -------------------------------------------------- ------
void timer_set()
{
TMOD=0x22; //Timer 1 is working mode 2 (8-bit automatic reload), 0 is mode 2 (8-bit automatic reload)
PCON=0x00;
TR0=0; //Start using when sending or receiving
TF0=0;
TH0=(256-96); //9600bps is 1000000/9600=104.167 microseconds. The timer to be executed is
//104.167*11.0592/12= 96
TL0=TH0;
ET0=1;
}
//------------------------------------------------ -------------------------------------------------- -----
// Function name: set_timer_interrupt
// Function description: Enable timer interrupt, related to hardware
//------------------------------------------------ -------------------------------------------------- ------
void set_timer_interrupt()
{
EA=1;
}
//------------------------------------------------ -------------------------------------------------- -----
// Function name: IntTimer0
// Function description: Timer interrupt function, related to hardware, but no processing is done, directly call the general interrupt processing function
//------------------------------------------------ -------------------------------------------------- ------
void IntTimer0() interrupt 1
{
timer_isr(); //Call interrupt processing function
}[page]
//------------------------------------------------ -------------------------------------------------- -----
// Function name: idle
// Function description: The execution program when waiting for the timer interrupt is related to the specific application
//------------------------------------------------ -------------------------------------------------- ------
void idle()
{
}
//------------------------------------------------ -------------------------------------------------- -----
// Function name: timer_isr
// Function description: Interrupt processing function, hardware-independent, general function
//------------------------------------------------ -------------------------------------------------- ------
void timer_isr(void) /*interrupt service routine*/
{
char mask, start_bit, flag_in;
//Sending program
if ( flag_tx_ready )
{
if ( --timer_tx_ctr<=0 )
{
mask = internal_tx_buffer&1;
internal_tx_buffer >>= 1;
if ( mask )
{
set_tx_pin_high();
}
else
{
set_tx_pin_low();
}
timer_tx_ctr = 3;
if ( --bits_left_in_tx<=0 )
{
flag_tx_ready = FALSE;
}
}
}
// Receiving procedure
if ( flag_rx_off == FALSE )
{
if (flag_rx_waiting_for_stop_bit)
{
if ( --timer_rx_ctr<=0 )
{
flag_rx_waiting_for_stop_bit = FALSE;
flag_rx_ready = FALSE;
internal_rx_buffer &= 0xFF;
if (internal_rx_buffer!=0xC2)
{
inbuf[qin] = internal_rx_buffer;
if ( ++qin>=IN_BUF_SIZE )
{
qin = 0;
}
}
}
}
else // rx_test_busy receiving busy
{
if ( flag_rx_ready == FALSE )
{
start_bit = get_rx_pin_status();
// Determine the starting position
if ( start_bit == 0 )
{
flag_rx_ready = TRUE;
internal_rx_buffer = 0;
timer_rx_ctr = 4;
bits_left_in_rx =
rx_num_of_bits;
rx_mask = 1;
}
}
else
{
if ( --timer_rx_ctr<=0 )
{
timer_rx_ctr = 3;
flag_in =
get_rx_pin_status();
if ( flag_in )
{
internal_rx_buffer |= rx_mask;
}
rx_mask <<= 1;
if ( --bits_left_in_rx<=0 )
{
flag_rx_waiting_for_stop_bit = TRUE;
}
}
}
}
}
}[page]
//------------------------------------------------ -------------------------------------------------- -----
// Function name: init_uart
// Function description: Initialize the asynchronous serial port, independent of hardware, general function
//------------------------------------------------ -------------------------------------------------- ------
void init_uart( void )
{
flag_tx_ready = FALSE;
flag_rx_ready = FALSE;
flag_rx_waiting_for_stop_bit = FALSE;
flag_rx_off = FALSE;
rx_num_of_bits = 10;
tx_num_of_bits = 10;
set_tx_pin_low();
timer_set();
set_timer_interrupt(); // Enable timer interrupt
}
//------------------------------------------------ -------------------------------------------------- -----
// Function name: get_char
// Input parameters: None
// Output parameter: ch, receive data
// Function description: Receive a byte, regardless of hardware, general function
//------------------------------------------------ -------------------------------------------------- ------
char get_char( void )
{
char ch;
do
{
while ( qout==qin )
{
idle();
}
ch = inbuf[qout] & 0xFF;
if ( ++qout>=IN_BUF_SIZE )
{
qout = 0;
}
}
while ( ch==0x0A || ch==0xC2 );
return( ch );
}
//------------------------------------------------ ----------------------------------------
// Function name: put_char
// Function description: Receive a byte, regardless of hardware, general function
//------------------------------------------------ ----------------------------------------
void put_char( char ch )
{
while ( flag_tx_ready );
user_tx_buffer = ch;
//Wake up the serial port
timer_tx_ctr = 3;
bits_left_in_tx = tx_num_of_bits;
internal_tx_buffer = (user_tx_buffer<<1) | 0x200;
flag_tx_ready = TRUE;
}
//------------------------------------------------ -------------------------------------------------- -----
// Function name: flush_input_buffer
// Function description: Initialize the buffer, independent of hardware, general function
//------------------------------------------------ -------------------------------------------------- ------
void flush_input_buffer(void)
{
qin = 0;
qout = 0;
}
//------------------------------------------------ ----------------------------------------
// Function name: kbhit
// Function description: Determine whether the receiving pointer is equal to the sending pointer. It has nothing to do with the hardware. It is a general function.
//------------------------------------------------ ----------------------------------------
char kbhit( void )
{
return( qin!=qout );
}
//------------------------------------------------ ----------------------------------------
// Function name: turn_rx_on
// Function description: Start receiving, independent of hardware, general function
//------------------------------------------------ ----------------------------------------
void turn_rx_on( void )
{
flag_rx_off = FALSE;
}
//------------------------------------------------ ----------------------------------------
// Function name: turn_rx_off
// Function description: Stop receiving, not related to hardware, general function
//------------------------------------------------ ----------------------------------------
void turn_rx_off( void )
{
flag_rx_off = TRUE;
}
;****************************************************** ***********
Previous article:Brushless DC motor controller based on dedicated single chip microcomputer
Next article:Delayed shutdown circuit for small single-chip computer system
Recommended ReadingLatest update time:2024-11-16 23:48
- Popular Resources
- Popular amplifiers
- Wireless Sensor Network Technology and Applications (Edited by Mou Si, Yin Hong, and Su Xing)
- Siemens Motion Control Technology and Engineering Applications (Tongxue, edited by Wu Xiaojun)
- Modern Electronic Technology Training Course (Edited by Yao Youfeng)
- Modern arc welding power supply and its control
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
- Op amp offset voltage and single or dual power supply issues?
- How to filter out 50HZ power frequency interference introduced by active filtering
- Is it the inverter or the integrator circuit?
- I have lived for more than 30 years and my brushing posture is wrong!
- Questions about the MSP430 microcontroller architecture: MSP430, MSP430X, MSP430Xv2
- Today at 10:00 AM, live broadcast with prizes: [Infineon Intelligent Motor Drive Solution]
- Technical staff salary
- Precision Wide Bandwidth, RMS to DC Converter
- RISC-V MCU Development Practice (Part 4): Stepper Motor
- The problem that PL2303 driver cannot be used under win10