Introduction to three methods of simulating serial ports using single-chip microcomputers
Instruction cycle s = (1000000/9600)/(12/11.0592) = 96, which is exactly an integer. If it is 4800BPS, it is 96x2=192, and if it is 19200BPS, it is 48. Other baud rates are not counted, and they are all exactly integer instruction cycles. Isn't it wonderful? As for
other crystal oscillator frequencies, you can calculate them by yourself.
Now let's take the 11.0592M crystal oscillator as an example to discuss three methods of simulating serial ports.
Method 1: Delay method
Through the above calculation, we know that each bit of the serial port needs a delay of 0.104 seconds, and 96 instruction cycles can be executed in the middle.
#define uchar unsigned char
sbit P1_0 = 0x90;
sbit P1_1 = 0x91;
sbit P1_2 = 0x92;
#define RXD P1_0
#define TXD P1_1
#define WRDYN 44 //Write delay
#define RDDYN 43 //Read delay
//Write a byte to the serial port
void WByte(uchar input)
{
uchar i=8;
TXD=(bit)0; //Send start
bit
Delay2cp(39);
//Send 8-bit data bit
while(i--)
{
TXD=(bit)(input&0x01); //Transmit low bit first
Delay2cp(36);
input=input>>1;
}
//Send check bit (none)
TXD=(bit)1; //Send end
bit
Delay2cp(46);
}
//Read a byte from the serial port
uchar RByte(void)
{
uchar Output=0;
uchar i=8;
uchar temp=RDDYN;
//Send 8-bit data
Delay2cp(RDDYN*1.5); //Note here, wait for the start bit
while(i--)
{
Output >>=1;
if(RXD) Output =0x80; //Receive the low bit first
Delay2cp(35); //(96-26)/2, the loop
takes up 26 instruction cycles in total
}
while(--temp) //Search for the end bit within the specified
time.
{
Delay2cp(1);
if(RXD)break; //Exit after receiving the end bit
}
return Output;
}
//Delay program*
void Delay2cp(unsigned char i)
{
while(--i); //Exactly two
instruction cycles.
} This method has certain difficulties in receiving, mainly because the sampling positioning needs to be more accurate, and the number of instruction cycles for each statement
must also be known .
This method can simulate several serial ports, and many people use it in practice. However, if you use Keil
C, I do not recommend this method. The above program has been tested on three single-chip computers: P89C52, AT89C52, and W78E52.
Method 2: Counting
method The counter of 51 increases by 1 in each instruction cycle until it overflows, and the hardware sets the overflow flag. In this way, we can
use the method of presetting the initial value to make the machine overflow once every 96 instruction cycles, and the program constantly queries the overflow flag to decide whether to
send or receive the next bit.
//Counter initialization
void S2INI(void)
{
TMOD =0x02; //Counter 0, mode 2
TH0=0xA0; //Pre-value is 256-96=140, hexadecimal A0
TL0=TH0;
TR0=1; //Start counting
TF0=0;
}
void WByte(uchar input)
{
//Send start bit
uchar i=8;
TR0=1;
TXD=(bit)0;
WaitTF0();
//Send 8-bit data
while(i--)
{
TXD=(bit)(input&0x01); //Transmit low bit first
WaitTF0();
input=input>>1;
}
//Send check bit (none)
//Send end bit
TXD=(bit)1;
WaitTF0();
TR0=0;
}
//Query counter overflow flag
void WaitTF0( void )
{
while(!TF0);
TF0=0;
}
For the receiving program, you can refer to the next method and will not write it out. I personally feel that this method is good. Both receiving and sending
are very accurate. In addition, there is no need to calculate the number of instruction cycles for each statement.
Method 3: Interrupt method The
interrupt method is similar to the counter method, except that an interrupt is generated when the counter overflows. The user can
set a flag in the interrupt program, and the program continuously queries the flag to decide whether to send or receive the next bit. Of course, the interrupt needs to be initialized in the program
, and the interrupt program is written at the same time. This program uses the Timer0 interrupt.
#define TM0_FLAG P1_2 //Set the transmission flag
//Initialize the counter and interrupt
void S2INI(void)
{
TMOD =0x02; //Counter 0, mode 2
TH0=0xA0; //Preset value is 256-96=140, hexadecimal A0
TL0=TH0;
TR0=0; //
Start using it when sending or receiving
TF0=0;
ET0=1; //Enable
timer 0 interrupt
EA=1; //Interrupt enable
master switch
}
//Receive a character
uchar RByte()
{
uchar Output=0;
uchar i=8;
TR0=1; //Start Timer0
TL0=TH0;
WaitTF0(); //Wait for the start
bit
//Send 8 data bits
while(i--)
{
Output >>=1;
if(RXD) Output =0x80; //Receive the low bit first
WaitTF0(); //Inter-bit delay
}
while(!TM0_FLAG) if(RXD) break;
TR0=0; //Stop
Timer0
return Output;
}
//Interrupt 1 handler
void IntTimer0() interrupt 1
{
TM0_FLAG=1; //Set flag.
}
//Query transmission flag
void WaitTF0( void )
{
while(!TM0_FLAG);
TM0_FLAG=0; //Clear flag
}
The interrupt method is also the method I recommend, which is similar to the counting method. The sending program refers to the counting method, which is believed to be a very easy
task.
It should also be noted that the serial port mentioned in this article is the usual three-wire asynchronous communication serial port (UART), which only uses RXD, TXD, and GND.
//****************************************************************
[page]
AVR software simulation serial port program
Source: coldra data room Author: coldra
Output: Use timer to control the output bit of ordinary IO port
Input: Use external interrupt + timer to determine the width of the bit
I haven't rested for several days. I wrote it in my spare time. I didn't find other people's reference programs, but it is finally stable. In fact, there should be many other methods to try, such as using PWM to output serial data, using input to capture received data, or timing query, or using any IO port interrupt, then each pin may be There are
still some problems now. When full-duplex is sending and receiving at the same time, the sending occasionally fails. It is a bit wasteful to occupy two timers. I will modify it later. It is best to add various wave rates
This program is directly extracted and the irrelevant parts are deleted. Some variables may be useless or paragraphs may be omitted. Please forgive me
#
include #include
#include
#include
#define Sbit1() PORTD =1<#define Sbit0() PORTD&=~(1<
volatile unsigned int
eep_ms,//millisecond timing
keytime, //wait time
SoundOnTime; ////
volatile unsigned char
rdata,
key,
start=0,
keycode, //
*TxPoint,
rtime,
INT0_time, //interrupt times
RxLength=0, //receive length
RUDR, //simulate serial port received data
TxLength, //serial port send data length
SUDR; //serial port send data
unsigned char arr[10],DispBuff[10];
void Initial_IO(void)//IO port initialization
{
DDRD = 0X82; //PD1 serial port output, PD0 serial port input, PD2 simulate serial port input (INT0)
PORTD = 0X82; //PD1 output high level
}
void Initial_INT0(void)
{
EICRA =(1< EIMSK =1< }
void Initial_timer0(void) //Timer0 initialization
{
TCCR0B =(1< TIMSK0 =(1< }
void Initial_timer1(void)
{
TCCR1A=(1< TCCR1B=(1< ICR1=1000;
TIMSK1 =(1< }
void Initial_timer2(void)
{
TCCR2B=(1< TIMSK2 =(1< }
void Initial_WDR(void) //Watchdog initialization
{
wdt_enable(WDTO_1S);
wdt_reset();
}
void Initial(void)
{
Initial_IO();
Initial_timer0(
);
Initial_timer1( );
Initial_timer2(); Initial_INT0();
Initial_WDR();
sei();
}
/
*
Start
serial
port sending*/
void
SendData
(unsigned char *P,unsigned char DataLength)
{
TxLength
=
DataLength
;
if((rdata)&&(eep_ms>10))//Start sending after receiving data with a delay of 10ms, and send back verification data
{
key=0;
SendData(&DispBuff[0],9);//Send 9 bits of data of DispBuff[0]
while(TxLength);//Wait for sending to complete
rdata=0;
eep_ms=0;
}
}
[page]
/*Timer 0, 100us overflow interrupt*/
SIGNAL(SIG_OVERFLOW0)
{
TCNT0=151;//Reload data, timing interval is 151---255, a total of 104uS, one bit time
if(TxLength)//
{
if(start==0)
{
Sbit0();//Start bit
SUDR=*(TxPoint++);
}
else
{
if((start<=8))
{
if(SUDR&(1<<(start-1)))Sbit1();//Data 1
else Sbit0();//Data 0
}
else Sbit1();//Stop bit
}
if(start<10)start++;
else
{
TxLength--;//One byte sent, the number of bytes minus 1
start=0;
}//
}
}
/*Timer 1, 1ms overflow interrupt*/
SIGNAL(SIG_OVERFLOW1)
{
eep_ms++;
}
/*Timer 2*/
SIGNAL(SIG_OVERFLOW2)
{
sei();
if(INT0_time)//There is data
{
INT0_time=0;//The number of interrupts is cleared to 0
rdata=1;//Set the data flag
eep_ms=0;
if(RxLength<10)DispBuff[RxLength++]=RUDR;
}
if(rtime<4)rtime++;//Byte interval time, restart a frame after 3 bytes
else RxLength=0;
}
SIGNAL(SIG_INTERRUPT0)//INT0, edge triggered interrupt
{
unsigned char temp,temp2=0;
static unsigned char pre_TCNT2,j=0;
if(INT0_time==0)//The first falling edge interrupt of a byte, starts from the start bit
{
TCNT2=130;
pre_TCNT2=130;
RUDR=0xff;//Initial value of received data
j=0; //The number of bits is cleared
INT0_time++; //The number of interrupts is increased by one
}
else
{
temp=TCNT2;
if(temp>pre_TCNT2)temp2=temp-pre_TCNT2; //Take a high/low level width
if(temp2>10) //Filter narrow level (interference signal)
{
pre_TCNT2=temp; //Record the previous time value
temp=0;
while(temp2>13) //Calculate the number of bits, about 13 is one bit (8*13=104uS)
{
temp2-=13; //
temp++;
}
if(temp2>6)temp++; //Calculate the number of bits, generally 13 is one bit
if(INT0_time==1)temp-=1;
if(INT0_time&1) //Odd number of interrupts
{
while(temp) //Number of bit 0s
{
RUDR&=~(1< temp--;
j++;
}
}
else j+=temp; //even number, number of 1 bits, skip
INT0_time++; //interrupt count plus one
}
}
rtime=0;
}
Previous article:Using 51 single chip microcomputer to realize serial port-Ethernet converter
Next article:A brief discussion on the application of single chip microcomputer in temperature control system
Recommended ReadingLatest update time:2024-11-16 19:39
- Popular Resources
- Popular amplifiers
- Wireless Sensor Network Technology and Applications (Edited by Mou Si, Yin Hong, and Su Xing)
- Modern Electronic Technology Training Course (Edited by Yao Youfeng)
- Modern arc welding power supply and its control
- Small AC Servo Motor Control Circuit Design (by Masaru Ishijima; translated by Xue Liang and Zhu Jianjun, by Masaru Ishijima, Xue Liang, and Zhu Jianjun)
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
- 5G commercial use is on the way, are you ready?
- Chat with Vicor engineers about efficient power supply and learn about modular power solutions for drones!
- Download the practical guide - Motor Control Basics
- DDR4 signal reference power layer, will the impedance have any impact?
- Questions about adjustable color temperature LED lamp circuit
- Oscilloscope test of auto repair model CAN line test
- How to Accurately Test Phase Noise
- [NXP Rapid IoT Review] Power on (finally received the goods)
- [XMC4800 Relax EtherCAT Kit Review] + Getting Started with DAVE, XMC4800 EtherCAT Slave Module Example Analysis
- Apply for the USB PD power receiving protocol chip CH224 and CH224EVT for free, show your DIY creativity and win Qinheng gifts!