The differences between RS232 and 485 levels, hardware peripheral chips, baud rate (reflecting the time to transmit one bit), start bit and stop bit, data width, checksum, hardware flow control, and the corresponding interface when connected to the computer. Configuration, use of functions, interrupts, queries and combined with communication protocols are considered to be understood in the use of serial ports.
The above is the basics. Of course, stm has many related multiplexing functions, supports synchronous one-way communication and half-duplex single-line communication, supports local Internet, smart card protocol and infrared data organization related specifications, as well as modem operation, and runs multi-processor communication. At the same time, DMA can be used for high-speed data communication. Pay attention to the time problem of Print function, try to solve it through DMA.
Features: Full-duplex, asynchronous, fractional baud rate generator has the advantage of fast speed, 8 or 9 bits, configurable 1 or 2 stop bits, Lin protocol, and can provide synchronous clock function.
Hardware
Generally there are two pins, RX and TX; the synchronous mode requires the SCLK clock pin, and the infrared IRDA requires the irDA_RDI pin as data input and irDA_TDO output.
Parity check is configured by the usart_cr1 pce bit (parity bit is generated when sending and checked when receiving)
LIN local area network mode: by setting the LINEN bit configuration in USART_CR2, a dedicated transceiver is required for use
Synchronous mode: Configure by setting the CLKEN bit in USART_CR2
Smart card mode: Configure by setting the SCEN bit in USART_CR3
Special research is done on DMA and hardware flow control.
What are the interrupt events?
Send data register empty Sending completed Receive data readable Parity error Data overflow CTS flag Idle flag Disconnect flag Noise flag
Unfortunately, there is no receiving buffer, so data loss is easy when using queries
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The process is clock configuration pin configuration (such as remapping, pin mode) - serial port configuration - interrupt configuration - corresponding interrupt - open serial port
The above are some basic knowledge points. Let's understand the serial port functions from practical applications.
A relatively simple application: initializing the usart
void COM1_Init( void)
{
//First, initialize the structure: the corresponding pins are indispensable, and the usart is also concerned with the interrupt configuration structure, defining space to be graffitied
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//The following is to graffiti
GPIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //Select pin position
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //Mode multiplexing push-pull output
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //Select pin position
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //Mode is input
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200; //Baud rate
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8 data bits
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1 stop bit
USART_InitStructure.USART_Parity = USART_Parity_No; //No parity check
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //No data flow control
USART_InitStructure.USART_Mode = USART_Mode_Rx USART_Mode_Tx; //Transmit and receive mode
USART_Init(USART1, &USART_InitStructure);
//Enable serial port interrupt and set priority
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = USART1_IRQn_Priority; NVIC_InitStructure.NVIC_IRQChannelSubPriority
=0; NVIC_InitStructure.NVIC_IRQChannelCmd
= ENABLE;
NVIC_Init(&NVIC_InitStructure); //Throw the structure into the configuration function, that is, write it to the corresponding register
//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//All the work is done, don't forget to open the serial port
USART_Cmd(USART1, ENABLE);
}
//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); Below is the interrupt source
#define USART_IT_PE ((uint16_t)0x0028)
#define USART_IT_TXE ((uint16_t)0x0727)
#define USART_IT_TC ((uint16_t)0x0626)
#define USART_IT_RXNE ((uint16_t)0x0525)
#define USART_IT_IDLE ((uint16_t)0x 0424)
#define USART_IT_LBD (( uint16_t)0x0846)
#define USART_IT_CTS ((uint16_t)0x096A)
#define USART_IT_ERR ((uint16_t)0x0060)
#define USART_IT_ORE ((uint16_t)0x0360)
#define USART_IT_NE ((uint16_t)0x0260)
#define USART_IT_FE ((uint16_t)0x0160)
--
The above is the initialization configuration. The following is a minimal application. Let's take the output function as an example.
void PrintUart1(const u8 *Str)
{
while(*Str)
{
USART_SendData(USART1, (unsigned char)*Str++);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
}
Sending characters is to continuously send the next data by querying the status of the string.
Receiving data is achieved through interrupts, and the received data is put into the buffer. The protocol will be discussed in detail later.
Want to play with computer serial port data transmission, and use printf() to display it directly in the computer window, isn't it great? Add in the usart.c function
//Do not use semihosting mode
#if 1 //If this section is not included, you need to select USE microLIB in the target option
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
FILE __stdout;
_sys_exit(int x)
{
x = x;
}
#endif
int fputc(int ch, FILE *f)
{
USART_SendData(USART1, (unsigned char)ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
return ch;
}
The above data sources can be through serial port, USB, wireless, etc. . .
The printf function has a flaw, which is that it takes too much time (in milliseconds). You can't let the CPU wait for a few milliseconds to display the serial port, otherwise even the best CPU will be wasted. What should we do? You can use DMA!! Let other hardware directly transfer these rough tasks. The CPU can do other important work!
Let's talk about serial port reception first, and then talk about DMA. There is a file in the firmware library that is specifically used to store interrupt processing functions.
There is a function
void USART1_IRQHandler(void)
{
static u8 UartBuf[UART_BUF_LEN]; //Serial port buffer
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
temp=USART_ReceiveData(USART1);
..............The following are some processing, you can use the state machine mode to play until the serial port buffer data is filled and verified to be correct, no more words
}
}
The above is a typical interrupt handling function, which is very powerful when combined with the state machine. When it comes to the operating system, you need to learn how to use it further.
Through the above study, I believe I have a deeper understanding of basic serial port operations. As mentioned earlier, printf is too slow, so some improvements are needed here.
Considering that the actual execution of serial port output (which is actually completed a few milliseconds later using DMA) is a few milliseconds later than the execution of pruntf (completed immediately), it has no impact on the actual application. Therefore, the CPU can command the DMA module to complete the task of serial port output in the tick interrupt. (In fact, it still has some impact on the system. From a macro perspective, the data output by the serial port is actually very small. Putting a cup of water in a river is almost negligible.)
Then solve how to allocate:
define two global buffers.
One of the buffers is organized in the form of a circular queue, and an element is added to the end of the queue each time fputc is executed.
The other buffer is directly organized in the form of an array as the source address of DMA.
In the tick interrupt, complete the DMA operation in the following order
(1) Determine whether the circular queue is empty. If it is empty, it means that there is no string that needs to be output through the serial port. Jump directly to (6)
(2) Determine whether DMA is working. If DMA is working, it means that any last assigned task has not been completed. Jump directly to (6)
(3) Dequeue N characters from the circular queue to the array cache
(4) Tell DMA the number of bytes N to be transferred this time
(5) Command DMA to start transferring
(6) End the operation
Supplement:
1. How to determine N: If the number of elements in the circular queue is greater than or equal to the length of the array cache (fixed value), assign
the length of the array cache to N. If the number of elements in the circular queue is less than the length of the array cache, assign the number of elements in the circular queue to N.
2. The larger the circular queue is, the more strings can be cached, so the larger the better.
3. The larger the array buffer is, the better it is. This value can be calculated as follows. Assuming the baud rate is 115200 and the tick interrupt
cycle is 2 milliseconds, then theoretically, a maximum of 115200*0.002/10=23 bytes can be transmitted in this 2 milliseconds. Therefore, the size of the array buffer
can be set to a slightly smaller size than 23, such as 20.
The code can run normally. After testing, it only takes 25 microseconds of CPU time to print a string containing 20 characters using the new solution,
while the old solution takes 1.76 milliseconds of CPU time. Therefore, you can safely use printf to debug some functions with high timing requirements.
In addition, the probability of printf being re-entered is greatly reduced due to the execution time period. If you need to completely prevent printf from being re-entered, you can turn off the interrupt before calling printf and turn on the interrupt after printf is executed. The cost is only a possible interrupt delay of tens of microseconds.
................................................................. ....................................................
Let me talk about my understanding of DMA
stm32 DMA has 8 channels, 07
Since DMA transfers data, of course there is a data width, which needs to be configured. In addition, there must be an address, which address to start the transfer from and which address to transfer to, which needs to be configured. For normal transfers, just transfer directly, and if you want to transfer continuously at high speed, this can also be configured. It is also possible to load directly from ROM to RAM quickly (not vice versa).
The above are some basic tasks that need to be configured
DMA_DeInit(DMA1_Channel4);
The above sentence is to configure the channel for DMA. According to the information provided by ST, the DMA in STM3210Fx contains 7 channels.
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&((USART_TypeDef *)USART1)->DR);
The above is to set the peripheral address
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) USART_DMA_BUF;
The above sentence is obviously the address of the variable in Memory that DMA is to be connected to, and the memory address is set above;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
The above sentence is to set the DMA transmission direction, just as I said before, from memory to peripherals, or from peripherals to memory: just change DMA_DIR_PeripheralSRC to DMA_DIR_PeripheralDST.
DMA_InitStructure.DMA_BufferSize = 0;
The above sentence sets the length of the DMA buffer during transmission. The starting address of the buffer has been defined before: For security and reliability, it is generally necessary to define a storage area for the buffer. There are three types of units for this parameter: Byte, HalfWord, and Word. I set 2 half-words (see the settings below); 1 half-word occupies 16 bits in a 32-bit MCU.
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
The above sentence is to set the peripheral increment mode of DMA. If the channel (CHx) selected by DMA has multiple peripherals connected, you need to use the peripheral increment mode: DMA_PeripheralInc_Enable; in my example, I use DMA_PeripheralInc_Disable
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
The above sentence sets the memory increment mode of DMA. When DMA accesses multiple memory parameters, DMA_MemoryInc_Enable needs to be used. When DMA only accesses one memory parameter, it can be set to: DMA_MemoryInc_Disable.
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
The above sentence is to set the data length of each operation when DMA accesses. There are three types of data length, which have been mentioned before and will not be described here.
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
The same as above. No further explanation is given here.
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
The above sentence sets the DMA transfer mode: continuous loop mode. If you only want to access it once and then not access it (or ask it in reverse according to the instruction operation, that is, access it when you want it to access, and stop it when you don’t want it to access), you can set it to the general mode: DMA_Mode_Normal
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
The above sentence is to set the DMA priority level: it can be divided into 4 levels: VeryHigh, High, Medium, Low.
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
The above sentence is to set the variables in the two memories of DMA to access each other.
DMA_Init(DMA_Channel1,&DMA_InitStructure);
The previous ones are settings for the DMA structure members. Now we will initialize the entire DMA module so that the DMA members are consistent with the above parameters.
DMA_Cmd(DMA_Channel1,ENABLE);
OK, the above configuration is completed, which is equivalent to setting a pipeline to send the data in the buffer to the serial port through DMA. Of course, to connect DMA to usart1, the DMA function of usart must be turned on in usart1: USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); Then in the program, you only need to monitor the status of data transmission and turn on or off DMA in time, leaving it for the next serial port transmission.
The printf() function is overloaded as follows
int fputc(int ch, FILE *f)
{
while(En_Usart_Queue(ch)==-1);
return ch;
}
The beginning is to add the data to be printed by the serial port to the circular buffer, which is a relatively fast action. Because the CPU moves data directly very quickly, and the serial port is operated by the CPU, waiting for the response, there is a while (..) which is relatively slow, so there is a delay of several milliseconds. Now, the CPU only moves the data to the buffer through printf. When the buffer is in a certain time, the CPU instructs DMA to start the next operation, and then DMA operates, and the CPU continues to do other things. It only needs to check whether DMA has completed the transmission or whether there is a transmission error when it is idle next time, and change the position of the first position of the circular queue, and change the corresponding status. This can greatly save a lot of time.
You can look at some algorithms for the structure of the circular queue, which is not very difficult.
The following is the function of CPU operation query during operation.
void DMA_USART_Handler(void){
u16 num=0;
s16 read;
if(DMA_GetCurrDataCounter(DMA1_Channel4)==0){ //Check whether DMA has completed the transmission task
DMA_Cmd(DMA1_Channel4, DISABLE);
while((read=De_Usart_Queue())!=-1){
USART_DMA_BUF[num]=read;
num++;
if(num==USART_DMA_BUF_SIZE)
break;
}
if(num>0){
((DMA_Channel_TypeDef *)DMA1_Channel4)->CNDTR = num;//Clear the quantity register
DMA_Cmd(DMA1_Channel4, ENABLE);
}
}
}
1. DMA principle:
DMA (Direct Memory Access) is an important feature of all modern computers. It allows hardware devices of different speeds to communicate without relying on a large interrupt load on the CPU. Otherwise, the CPU needs to move each piece of data from the source to the register, and then write it back to the new location again. During this time, the CPU is unavailable for other work.
DMA transfers move data from one address space to another. While the CPU initiates the transfer, the transfer itself is performed and completed by the DMA controller. A typical example is moving a block of external memory to a faster memory area inside the chip. Operations like this do not delay the processor's work, but can be rescheduled to handle other tasks.
2. STM32 uses DMA
1.DMA settings:
The configurations include DMA transfer channel selection, transfer members and direction, normal mode or circular mode, etc.
{
DMA_InitTypeDef DMA_InitStructure;
//DMA settings:
//Set DMA source: memory address & serial port data register address
//Direction: memory-->peripheral
//Each transfer bit: 8bit
//Transfer size DMA_BufferSize=SENDBUFF_SIZE
//Address auto-increment mode: peripheral address does not increase, memory address auto-increment 1
//DMA mode: one-time transfer, non-cyclic
//Priority: medium
DMA_DeInit(DMA1_Channel4); //The DMA transmission channel of serial port 1 is channel 4
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff; //Data address accessed by DMA
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //Peripheral as the destination of DMA
DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE; //Transfer data size
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //Peripheral address does not increase
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //Memory address increases by 1
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //(DMA transmission priority is medium)
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
}
vu8 SendBuff[SENDBUFF_SIZE];
SendBuff[i] = i+'0';
}
4. Start DMA transfer (enable the corresponding DMA channel)
DMA_Cmd(DMA1_Channel4, ENABLE);
{
LED_1_REV; //LED changes on and off
Delay(); //waste time
}
#include "stm32f10x_lib.h"
#include "stdio.h"
#define USART1_DR_Base 0x40013804
#define SENDBUFF_SIZE 10240
vu8 SendBuff[SENDBUFF_SIZE];
vu8 RecvBuff[10];
vu8 recv_ptr;
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void DMA_Configuration(void);
void USART1_Configuration(void);
void Delay(void);
int main(void)
{
u16 i;
#ifdef DEBUG
debug();
#endif
recv_ptr = 0;
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
DMA_Configuration();
USART1_Configuration();
printf("\r\nSystem Start...\r\n");
printf("Initialling SendBuff... \r\n");
for(i=0;i
SendBuff[i] = i+'0';
}
printf("Initial success!\r\nWaiting for transmission...\r\n");
//The data to be sent is ready. Press the button to start the transmission
while(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_3));
printf("Start DMA transmission!\r\n");
//Here are some preparations before starting DMA transmission. Set the USART1 module to work in DMA modeUSART_DMACmd
(USART1, USART_DMAReq_Tx, ENABLE);
//Start a DMA transmission!
DMA_Cmd(DMA1_Channel4, ENABLE);
//Wait for DMA transmission to complete. Now we can do other things, such as turning on the light.
//In actual applications, other tasks can be performed during data transmissionwhile
(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET)
{
Delay(); //Waste of time
}
//After DMA transmission, the DMA channel is automatically closed without manual closing.
//The following statements are commented
//DMA_Cmd(DMA1_Channel4, DISABLE);
printf("\r\nDMA transmission successful!\r\n");
while (1)
{
}
}
int fputc(int ch, FILE *f)
{
//USART_SendData(USART1, (u8) ch);
USART1->DR = (u8) ch;
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
{
}
}
void Delay(void)
{
u32 i;
for(i=0;i<0xF0;i++);
return;
}
void RCC_Configuration(void)
{
ErrorStatus HSEStartUpStatus;
RCC_HSEConfig(RCC_HSE_ON);
//Wait for external crystal oscillator to stabilize
HSEStartUpStatus = RCC_WaitForHSEStartUp();
//If the external crystal oscillator starts successfully, proceed to the next step
if(HSEStartUpStatus==SUCCESS)
{
//Set HCLK (AHB clock) = SYSCLK
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_PCLK2Config(RCC_HCLK_Div1);
//Recommended value: SYSCLK = 0~24MHz Latency=0
// SYSCLK = 24~48MHz Latency=1
// SYSCLK = 48~72MHz Latency=2
FLASH_SetLatency(FLASH_Latency_2);
//Enable FLASH prefetch buffer function
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
//Start PLL
RCC_PLLCmd(ENABLE);
//Wait for PLL to stabilize
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
//System clock SYSCLK comes from PLL output
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//Wait for system clock to stabilize after switching clock
while(RCC_GetSYSCLKSource()!=0x08);
}
//Start GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA RCC_APB2Periph_GPIOB \
RCC_APB2Periph_GPIOC RCC_APB2Periph_GPIOD,\
ENABLE);
//Start AFIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//Start USART1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//Start DMA clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 GPIO_Pin_5 GPIO_Pin_6 GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, & GPIO_InitStructure);
//Located at pins 3 4 11-15 of the PD port, enable setting as input
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 GPIO_Pin_4 GPIO_Pin_11 GPIO_Pin_12 \
GPIO_Pin_13 GPIO_Pin_14 GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART1_RX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// Set the Vector Table base location at 0x20
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else
// Set the Vector Table base location at 0x08
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//Enable serial port receive interrupt
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART1_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits =
USART_StopBits_1; USART_InitStructure.USART_Parity
= USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx USART_Mode_Rx;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
}
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
//DMA settings:
//Set DMA source: memory address & serial port data register address
//Direction: memory-->peripheral
//Each transfer bit: 8bit
//Transfer size DMA_BufferSize=SENDBUFF_SIZE
//Address auto-increment mode: peripheral address does not increase, memory address auto-increment 1
//DMA mode: one-time transfer, non-cyclic
//Priority: medium
DMA_DeInit(DMA1_Channel4); //The DMA transmission channel of serial port 1 is channel 4
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //Peripheral as the destination of DMA
DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE; //Transfer size
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //Peripheral address does not increase
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //Memory address increases by 1
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA_Mode_Normal (transmit only once), DMA_Mode_Circular (transmit continuously)
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //(DMA transfer priority is medium)
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
}
Previous article:STM32 defect 1: serial port interrupt flag defect
Next article:Detailed explanation of STM32 water temperature control system hardware
Recommended ReadingLatest update time:2024-11-17 01:33
- Popular Resources
- Popular amplifiers
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!
- Rambus Launches Industry's First HBM 4 Controller IP: What Are the Technical Details Behind It?
- 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
- Communication protocol conversion
- New live broadcast calendar
- LOTO Practice [Dry Goods] 2- Quick Application of Voltage Comparator
- GD32E230C Test 2: I2C and EEPROM
- [Chuanglong TL570x-EVM] Unboxing
- Random Questions about Operational Amplifier Circuits
- 【XMC4800 Relax EtherCAT Kit Review】+DAVE integrated development environment construction and demo operation
- Design of data acquisition card based on FPGA.pdf
- Actual development and experience of the first phase
- 【National Technology N32G430】02 Small expansion, communication from top to bottom