stm32和python实现DMA+串口数据收发

这篇具有很好参考价值的文章主要介绍了stm32和python实现DMA+串口数据收发。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

STM32F103配置

1-0 串口配置

void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	//使能USART1时钟
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE); //复位串口1
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE);
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //TX PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//RX PA.10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//子优先级1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
  //USART 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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_Rx | USART_Mode_Tx;	//收发模式

  USART_Init(USART1, &USART_InitStructure); //初始化串口1
	
//  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断 ???
  USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); // 空闲中断,打开接收中断。
  USART_Cmd(USART1, ENABLE);                    //使能串口1 
	usart1_dma_tx_init();
	usart1_dma_rx_init();	
}

1-1 DMA发送模式配置

static void usart1_dma_tx_init(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    DMA_DeInit(DMA1_Channel4);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)usart1_tx_buff;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = 0;/*避免初始化发送数据,设置为0*/
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    DMA_Cmd(DMA1_Channel4, ENABLE);
}

1-2 通过DMA传输数据到USART1的发送寄存器

// 用于通过DMA传输数据到USART1的发送寄存器
uint8_t usart1_dma_tx_data(void* buffer, uint16_t data_lenth)
{
	if(data_lenth < 1)// 判断长度是否有效
	{
		return ERROR;
	}
	
	while (DMA_GetCurrDataCounter(DMA1_Channel4));// 检查DMA发送通道内是否还有数据
	if(NULL == buffer)//指针判空
	{
		return ERROR;
	}
	
	USART1_state.txc = RESET; // 表示发送未完成。
	// 使用memcpy函数将buffer中的数据复制到usart1_tx_buff中。
	// 复制的长度为data_lenth和USART1_TX_BUFF_MAX_LENTH中较小的值。这是为了防止数据溢出。
	memcpy(usart1_tx_buff, buffer,((data_lenth > USART1_TX_BUFF_MAX_LENTH) ? USART1_TX_BUFF_MAX_LENTH:data_lenth));
	
    DMA_Cmd(DMA1_Channel4, DISABLE); //DMA发送数据-要先关 ,以确保设置发送长度之前DMA传输已经停止。
    DMA_SetCurrDataCounter(DMA1_Channel4, data_lenth);// 设置DMA1_Channel4的发送长度为data_lenth。
    DMA_Cmd(DMA1_Channel4, ENABLE);// 启用DMA1_Channel4,以启动DMA传输
	
	return SUCCESS;
}

1-3 串口数据发送

将usart1_dma_tx_data()函数放在main函数中或者中断处理函数中即可,如下所示:文章来源地址https://www.toymoban.com/news/detail-625137.html

void main()
{
    uint8_t data_array[8];
	data_array[0] =  0x12;
	data_array[1] =  0x34;
	data_array[2] = (int)Encoder & 0xFF;
	data_array[3] = ((int)Encoder >> 8) & 0xFF;
	data_array[4] = (int)Adc & 0xFF;
	data_array[5] = ((int)Adc >> 8) & 0xFF;
	data_array[6] =  0x56;
	data_array[7] =  0x78;
	usart1_dma_tx_data(data_array, 8);
}

2-1 DMA接收模式配置

#define USART1_RX_BUFF_MAX_LENTH 200    //定义最大接收字节数 200
#define USART1_TX_BUFF_MAX_LENTH 200
static void usart1_dma_rx_init(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    DMA_DeInit(DMA1_Channel5);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;           // 初始化外设地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)usart1_rx_buff;            // 缓存地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                     // 外设作为数据来源
    DMA_InitStructure.DMA_BufferSize = USART1_RX_BUFF_MAX_LENTH;           // 缓存容量
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;       // 外设地址不递增
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                // 内存递增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;// 外设字节宽度
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;        // 内存字节宽度
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;						   // 正常模式,即满了就不在接收了,而不是循环存储
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                    // 优先级很高
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                           // 内存与外设通信,而非内存到内存
    DMA_Init(DMA1_Channel5, &DMA_InitStructure);
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
    DMA_Cmd(DMA1_Channel5, ENABLE);
}

2-2 串口结束中断

void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)/*空闲中断接收*/
    {
        u8 data_lenth = 0 ;
		
        DMA_Cmd(DMA1_Channel5, DISABLE);// 关闭DMA ,防止干扰
		USART_ReceiveData( USART1 );
		
        data_lenth = USART1_RX_BUFF_MAX_LENTH - DMA_GetCurrDataCounter(DMA1_Channel5);//获得接收到的字节数
        DMA_SetCurrDataCounter(DMA1_Channel5, USART1_RX_BUFF_MAX_LENTH);//  重新赋值计数值,必须大于等于最大可能接收到的数据帧数目
        DMA_Cmd(DMA1_Channel5, ENABLE);
				USART1_state.rxc = SET;  //设置接收完成标志
		
		my_usmart_scan(usart1_rx_buff,data_lenth); //配置自己的接收处理函数//执行usmart扫描	
		
        memset(usart1_rx_buff, 0, USART1_RX_BUFF_MAX_LENTH); //清空接收缓存区		 
				USART_ClearITPendingBit(USART1, USART_IT_IDLE); // Clear IDLE interrupt flag bit
    }
		if(USART_GetITStatus(USART1,USART_IT_TC) != RESET)  //发送完成标记
		{
			DMA_Cmd(DMA1_Channel4, DISABLE);                // 关闭DMA
			DMA_SetCurrDataCounter(DMA1_Channel4,RESET);    // 清除数据长度
			USART1_state.txc = SET;                         // 设置发送完成标志
			USART_ClearITPendingBit(USART1, USART_IT_TC);   // 清除完成标记
		}	
}

2-3 对串口接收的数据进行处理

void my_usmart_scan(uint8_t * data_array,uint8_t data_lenth)
{
	if(SET == USART1_state.rxc)//串口接收完成标志位
	{					   
			if(data_array[0] == 0x2D && data_array[1] == 0x01 && data_array[5] == 0x56 && data_array[6] == 0x78) // 判断帧头1和2是否正确、帧尾1和2是否正确 
			{
				float value = 0;
				int16_t sign = 1;
				if(data_array[2] == 0x45) // 符号位判断
				{
					sign = -1;
				}
				value = (data_array[4] << 8) + data_array[3];	
				action = sign * value;  // 接收的数据
		}																			
		USART1_state.rxc = RESET;//状态寄存器清空	    
	}	
}	 
	 

python上位机程序

# 从串口接收的数据为:编码器(整型)、角位移传感器(浮点型)
def read_serial_one_data_encoder_adc(ser):
    global receive_result
    BUF_SIZE = 8
    buf = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
    c1 = ib = flag = 0

    while True:
        R = ser.read(1)
        # print("data", R)
        if R == b'':
            print("Read Fail")
            ser.close()
            break
        c = int.from_bytes(R, byteorder='big')
        # print("data", c)
        if flag > 0:
            if ib < BUF_SIZE:
                buf[ib] = c
                ib += 1
            if ib == 8:
                if buf[6] == 0x56 and buf[7] == 0x78:
                    Encoder = (buf[3] << 8) + buf[2]
                    Adc= (buf[5] << 8) + buf[4]
                    receive_result = [Encoder, Adc]
                    break
                else:
                    print("CRC Fail")
                flag = 0
        if flag == 0:
            if c1 == 0x12 and c == 0x34:
                flag = 1
                ib = 2
        c1 = c
    return receive_result

def run_play():
    result = [0, 0]
    action = bytearray([0x12, 0x34, 0x00, 0x00, 0x00, 0x56, 0x78])
    ser = serial.Serial(  # 下面这些参数根据情况修改
        port='COM8',  # 串口
        baudrate=921600,  # 波特率
        timeout=None,
        parity=serial.PARITY_ODD, #
        stopbits=serial.STOPBITS_ONE,
        bytesize=8
    )
    if ser.isOpen():  # 判断串口是否打开
        print("open success")
    for i in range(1000000):
        result2 = read_serial_one_data_encoder_adc(ser)                    # /************从串口接收数据函数**************/
        print("result2=",result)
        ser.write(action) # 使用DMA需要多个字节一起发送                       /************往串口发送数据函数**************/

if __name__ == '__main__':
    run_play()

3 完整程序

#include "sys.h"
#include "usart.h"
#include <string.h>
#include <math.h>
#include <stdio.h>
uint16_t Res;
float action;
uint16_t check_flag;

#define USART1_RX_BUFF_MAX_LENTH 200    //定义最大接收字节数 200
#define USART1_TX_BUFF_MAX_LENTH 200

uint8_t ReceiveBuff[RECEIVEBUFF_SIZE];
static uint8_t usart1_tx_buff[USART1_TX_BUFF_MAX_LENTH];
uint8_t usart1_rx_buff[USART1_RX_BUFF_MAX_LENTH];

typedef struct
{
	uint8_t rxc;
	uint8_t txc;
}uart_state_t;

uart_state_t USART1_state;

// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif  

//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
重定义fputc函数 
//int fputc(int ch, FILE *f)
//{      
//	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
//    USART1->DR = (u8) ch;      
//	return ch;
//}
#endif 
#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  
  
void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	//使能USART1时钟
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE); //复位串口1
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE);
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //TX PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//RX PA.10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//子优先级1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
  //USART 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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_Rx | USART_Mode_Tx;	//收发模式

  USART_Init(USART1, &USART_InitStructure); //初始化串口1
	
//  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断 ???
  USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); // 空闲中断,打开接收中断。
  USART_Cmd(USART1, ENABLE);                    //使能串口1 
	usart1_dma_tx_init();
	usart1_dma_rx_init();	
}


static void usart1_dma_tx_init(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    DMA_DeInit(DMA1_Channel4);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)usart1_tx_buff;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = 0;/*避免初始化发送数据,设置为0*/
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    DMA_Cmd(DMA1_Channel4, ENABLE);
}
// 用于通过DMA传输数据到USART1的发送寄存器
uint8_t usart1_dma_tx_data(void* buffer, uint16_t data_lenth)
{
	if(data_lenth < 1)// 判断长度是否有效
	{
		return ERROR;
	}
	
	while (DMA_GetCurrDataCounter(DMA1_Channel4));// 检查DMA发送通道内是否还有数据
	if(NULL == buffer)//指针判空
	{
		return ERROR;
	}
	
	USART1_state.txc = RESET; // 表示发送未完成。
	// 使用memcpy函数将buffer中的数据复制到usart1_tx_buff中。
	// 复制的长度为data_lenth和USART1_TX_BUFF_MAX_LENTH中较小的值。这是为了防止数据溢出。
	memcpy(usart1_tx_buff, buffer,((data_lenth > USART1_TX_BUFF_MAX_LENTH) ? USART1_TX_BUFF_MAX_LENTH:data_lenth));
	
    DMA_Cmd(DMA1_Channel4, DISABLE); //DMA发送数据-要先关 ,以确保设置发送长度之前DMA传输已经停止。
    DMA_SetCurrDataCounter(DMA1_Channel4, data_lenth);// 设置DMA1_Channel4的发送长度为data_lenth。
    DMA_Cmd(DMA1_Channel4, ENABLE);// 启用DMA1_Channel4,以启动DMA传输
	
	return SUCCESS;
}


static void usart1_dma_rx_init(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    DMA_DeInit(DMA1_Channel5);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;           // 初始化外设地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)usart1_rx_buff;            // 缓存地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                     // 外设作为数据来源
    DMA_InitStructure.DMA_BufferSize = USART1_RX_BUFF_MAX_LENTH;           // 缓存容量
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;       // 外设地址不递增
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                // 内存递增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;// 外设字节宽度
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;        // 内存字节宽度
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;						   // 正常模式,即满了就不在接收了,而不是循环存储
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                    // 优先级很高
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                           // 内存与外设通信,而非内存到内存
    DMA_Init(DMA1_Channel5, &DMA_InitStructure);
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
    DMA_Cmd(DMA1_Channel5, ENABLE);
}

void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)/*空闲中断接收*/
    {
        u8 data_lenth = 0 ;
		
        DMA_Cmd(DMA1_Channel5, DISABLE);// 关闭DMA ,防止干扰
				USART_ReceiveData( USART1 );
		
        data_lenth = USART1_RX_BUFF_MAX_LENTH - DMA_GetCurrDataCounter(DMA1_Channel5);//获得接收到的字节数
        DMA_SetCurrDataCounter(DMA1_Channel5, USART1_RX_BUFF_MAX_LENTH);//  重新赋值计数值,必须大于等于最大可能接收到的数据帧数目
        DMA_Cmd(DMA1_Channel5, ENABLE);
				USART1_state.rxc = SET;  //设置接收完成标志
		
				my_usmart_scan(usart1_rx_buff,data_lenth); //配置自己的接收处理函数//执行usmart扫描	
		
        memset(usart1_rx_buff, 0, USART1_RX_BUFF_MAX_LENTH); //清空接收缓存区		 
				USART_ClearITPendingBit(USART1, USART_IT_IDLE); // Clear IDLE interrupt flag bit
    }
		if(USART_GetITStatus(USART1,USART_IT_TC) != RESET)  //发送完成标记
		{
			DMA_Cmd(DMA1_Channel4, DISABLE);                // 关闭DMA
			DMA_SetCurrDataCounter(DMA1_Channel4,RESET);    // 清除数据长度
			USART1_state.txc = SET;                         // 设置发送完成标志
			USART_ClearITPendingBit(USART1, USART_IT_TC);   // 清除完成标记
		}	
}
	 
///********************************************************
//Function:   void my_usmart_scan(uint8_t * data_array,uint8_t data_lenth)
//Description:处理接收数据
//Input:
//Output:
//Others:
//*********************************************************/
void my_usmart_scan(uint8_t * data_array,uint8_t data_lenth)
{
	if(SET == USART1_state.rxc)//串口接收完成标志位
	{					   
			if(data_array[0] == 0x2D && data_array[1] == 0x01 && data_array[5] == 0x56 && data_array[6] == 0x78) // 判断帧头是否正确、判断奇偶校验位是否正确 || USART_RX_BUF[1] == check_flag
			{
				float value = 0;
				int16_t sign = 1;
					if(data_array[2] == 0x45)
					{
						sign = -1;
					}
					value = (data_array[4] << 8) + data_array[3];	
					action = sign * value;
		}																			
		USART1_state.rxc = RESET;//状态寄存器清空	    
	}	
}	 
	 

到了这里,关于stm32和python实现DMA+串口数据收发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32F407学习DAY.14 在DMA模式下进行USART串口数据收发(正点原子例程为例)

    目录 一、DMA配置 1、DMA1和DMA2的请求映射 2、DMA挂载总线 3、DMA相关库函数 ​4、DMA配置过程(以串口1为例) 1)进行时钟使能 2)等待DMA可配置 3)初始化DMA(串口1的TX为DMA2 数据流7 通道4,RX为DMA2 数据流5 通道4) a.DMA外设地址par: b.DMA存储器0地址mar: c.数据传输量ndtr: 4)

    2024年02月04日
    浏览(49)
  • Stm32407串口1空闲中断+DMA收发(基于标准库实现)

    stm32串口的配置很简单,这里就不赘述了,使用 USART_SendData() 阻塞模式发送数据,或是接收中断配置 “接收缓冲区非空” USART_IT_RXNE ,这种做法效率很低,而且来一个数据中断一次数据处理起来也麻烦。 这里基于STM32F407提供一种串口空闲中断+DMA接收的方式,通过库函数编程

    2024年02月16日
    浏览(54)
  • STM32实现DMA接收串口数据

    一..首先我们得配置DMA和USARAT,我们的原理是DMA1的通道5为USART1的RX引脚。  1.USART1的配置 2.DMA的配置 二.中断进行数据处理(stm32f10x_it.c) 我们可以串口打印出数组中的数据,验证DMA是否正常工作。可以到数据处理那个地方进行处理。USART1在初始化中就已经波特率为115200.我们可以

    2024年02月16日
    浏览(47)
  • 【STM32】STM32F103C8T6串口通信,实现3个串口收发数据

    串口通信(Serial Communications)实现单片机与电脑或者其它外设进行通信,通信时只需两根线(TX,RX)就可以实现数据传输。STM32f103有三个串口,分别为串口1(RX PA10, TX PA 9),串口2(RX PA3,TX PA2),串口3(RX PB11,TX PB10)。 以下代码是配置三个串口: usart.c usart.h main.c 注意,

    2024年02月12日
    浏览(54)
  • STM32 F4串口空闲中断 + DMA实现数据发送

    最近在做 STM32 + ROS车的项目,STM32与ROS之间通信由于数据量大,所以在 STM32端 使用 空闲中断 + DMA 的方案来减轻 CPU 的压力。 一、空闲中断 空闲中断 顾名思义为空了,闲了,没事了进的中断,在 没有数据流 的时候会进入进行读取。 在我们串口进行发送时实则为连续发送,两

    2024年02月16日
    浏览(64)
  • STM32F407普通IO口模拟串口实现不定长数据收发

    因为项目中用到的串口比较多,STM32F407VET6自带的串口不够用了,所以只能考虑用模拟串口来实现功能。普通的IO口来模拟串口需要先了解串口的时序图,需要用到两个IO引脚即收发引脚,两个定时器,一个用于发送延时使用,一个用于产生中断接收数据。代码的初始化主要用

    2024年02月07日
    浏览(49)
  • 【STM32 HAL库实战】串口DMA + 空闲中断 实现不定长数据接收

    STM32CubeMX最新版: 打开STM32CubeMX软件,点击ACCESS TO MCU SELECTOR,在Commercial Part Number 中输入MCU型号,例如我在这里输入了STM32L431RCT6。选中正确型号然后双击进入下一步的配置界面。 1.1 SYS配置如图 1.2 RCC配置如图 开启了外部晶振,若无则都选择Disable 1.3 USART1配置 NVIC Settings 注意

    2024年02月03日
    浏览(80)
  • STM-32:串口收发数据包—串口收发HEX数据包/串口收发文本数据包

    1、包头包尾和数据载荷重复的问题,传输的数据本身是FF和FE,可能引起误判 解决:限制载荷数据的范围,限幅(例如只发送0~100) 如果无法避免数据与包头包尾重复,则尽量使用固定长度的数据包 增加包头包尾的数量,尽量是其呈现出载荷数据出现不了的状态 2、包头包尾并

    2024年02月03日
    浏览(48)
  • STM32使用三种方式(阻塞、中断、DMA)实现串口发送和接收数据

    记录下学习STM32开发板的心得的和遇见的问题。 板卡型号:STM32F405RGT6 软件:STM32CubeMX、IAR STM32串口外设提供了3种接收和发送方式:阻塞、中断、DMA,主要给大家分享中断方式接收不定长数据和DMA使用空闲中断接收不定长数据。 阻塞发送: 阻塞接收: 两个函数需要注意的就

    2024年02月03日
    浏览(52)
  • stm32串口空闲中断+DMA传输接受不定长数据+letter shell 实现命令行

    空闲中断(IDLE),俗称帧中断,即第一帧数据接收完毕到第二帧数据开始接收期间存在一个空闲状态(每接收一帧数据后空闲标志位置1),检测到此空闲状态后即执行中断程序。 空闲中断的优点在于省去了帧头帧尾的检测 ,进入中断程序即意味着已经接收到一组完整数据,仅需

    2024年02月03日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包