Experiment of simulating serial port using ordinary IO port of STM32F103RCT6

Publisher:Yuexiang888Latest update time:2018-09-09 Source: eefocusKeywords:STM32F103RCT6 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Use STM32CubeMX and Keil (HAL library)
Materials: stm32 development board, USB to TTL? CH340 module, Dupont line, st-link

Experimental principle:

Simulates asynchronous half-duplex communication

Variable baud rate

Start bit: 1
Data bit: 8
Stop bit: 1
(10 bits per data)
No parity bit


When transmitting a character, a start bit is sent first, followed by 8 data bits (from low to high), and finally a stop bit.


Use an ordinary GPIO port output (simulating TXD) to simulate the high and low levels sent above, and use timer delay (the duration of the level corresponding to one bit is 1000000/baud rate μs)
Use an ordinary GPIO port interrupt input (simulating RXD) to simulate reception, trigger interrupts on the falling edge, use timer delay, and collect level data once in the center of the data bit

Experimental design:
Use PA1 as TXD, PA2 as RXD, and then connect to the CH340 module and then to the computer
TIM2 delay

experiment procedure:


The test uses a baud rate of 9600

At first, we only realized the initial sending of "hello" and the correct sending and receiving of 2 bits of data in the loopback test. . .

It is inferred that the sending function of PA1 should be successful (however, after testing with a logic analyzer, the delay of one bit sent by PA1 reaches about 106us, which should be 104us under normal circumstances). There is a bug in the receiving function of PA2, which can only correctly receive 2 bits of data at a time, and the characters received afterwards are all wrong. It is speculated that it is a problem of time error in the delay, and it will automatically increase characters like spaces (after testing with a logic analyzer, it is actually a character with an ascii code of 255. After multiple tests, it was found that the interrupt should be triggered after receiving all the characters, but the subsequent levels are all high, so this character is received). . .

Wrong result:



Then change the code based on the speculation, reduce the delay time in the received data, and ignore the characters with ascii code 255 (a simple and crude method...)

Correct result:



Main settings in STM32CubeMX:







Main code (the following is only the code in USER CODE BEGIN):

/* USER CODE BEGIN Includes */

#include

/* USER CODE END Includes */

/* USER CODE BEGIN PV */

/* Private variables ---------------------------------------------------------*/

uint32_t baudrate=9600; //Set the baud rate, for example 9600bps

uint8_t message[20]; //The character array where the received characters are stored

uint8_t length=0; //Number of characters received

uint8_t welcome[]="hello"; //An initial message to be sent

uint32_t bit_time;

/* USER CODE END PV */


/* USER CODE BEGIN PFP */

/* Private function prototypes -----------------------------------------------*/

void delay_us(uint32_t counter);

void transmitChar(uint8_t ch);

uint8_t receiveChar(void);

void transmitString(uint8_t a[]);

/* USER CODE END PFP */

  /* USER CODE BEGIN 1 */

bit_time=1000000/baudrate; //One bit time, unit is us

  /* USER CODE END 1 */

  /* USER CODE BEGIN 2 */

transmitString(welcome); //Send initial information

  /* USER CODE END 2 */


/* USER CODE BEGIN 4 */

 

//Delay counter (us)

void delay_us(uint32_t counter){  

counter++;

HAL_TIM_Base_Start(&htim2);

__HAL_TIM_SET_COUNTER(&htim2,counter);

while(counter>1){

counter=__HAL_TIM_GET_COUNTER(&htim2); 

}

HAL_TIM_Base_Stop(&htim2);

}

 

 

//Send characters

void transmitChar(uint8_t ch){

HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,(GPIO_PinState)0);

delay_us(bit_time);

uint8_t i,temp;

for(i=0;i<8;i++){

temp=ch&0x01;

HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,(GPIO_PinState)temp);

delay_us(bit_time);

ch>>=1;

}

HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,(GPIO_PinState)1);

delay_us(bit_time);

}

 

 

//Send string

void transmitString(uint8_t a[]){

uint8_t i,j;

j=strlen(a);

for(i=0;i

transmitChar(a[i]);

}

}

 

 

//Receive characters

uint8_t receiveChar(void){

uint8_t bit,i,ch=0;

delay_us(bit_time*1.5);

for(i=0;i<8;i++){

bit=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2);

ch>>=1;

if(bit){

ch=ch|0x80;

}

delay_us(bit_time);

}

delay_us(bit_time*0.2);

return ch;

}

 

 

//GPIO interrupt callback function

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

  /* Prevent unused argument(s) compilation warning */

  UNUSED(GPIO_Pin);

uint8_t ch;

ch=receiveChar();

if(ch=='#'){

uint8_t i;

for(i=0;i

transmitChar(message[i]);

}

length=0;

}

else if(ch!=255){

message[length++]=ch;}

}

 

/* USER CODE END 4 */



Experimental results:


The correct transmission and reception of less than 19 characters is achieved (the character array of 20 elements, the reception of more characters has not been tested...)


Keywords:STM32F103RCT6 Reference address:Experiment of simulating serial port using ordinary IO port of STM32F103RCT6

Previous article:STM32 JTAG debug interface PB3, PB4 multiplexing problem
Next article:STM32 I/O as external interrupt input

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号