stm32f405串口 DMA+空闲中断 不定长数据收发代码

stm32f405串口 DMA+空闲中断 不定长数据收发代码

 

#include "sys.h"
#include "usart.h"
#include <string.h>
#include "led.h"
//
//
/*
//1,串口通信
UART1_TX PA9  DMA2_Stream7
UART1_RX PA10 DMA2_Stream2
UART2_TX PA2  DMA1_Stream6
UART2_RX PA3  DMA1_Stream5
UART3_TX PB10 DMA1_Stream3
UART3_RX PB11 DMA1_Stream1
UART4_TX PC10 DMA1_Stream4
UART4_RX PC11 DMA1_Stream2
UART5_TX PC12 DMA1_Stream7
UART5_RX PD2  DMA1_Stream0
UART6_TX PC6  DMA2_Stream6
UART6_RX PC7  DMA2_Stream1
*/
#define DMA2_Stream7_Tx1 DMA2_Stream7
#define DMA2_Stream2_Rx1 DMA2_Stream2

#define DMA1_Stream6_Tx2 DMA1_Stream6
#define DMA1_Stream5_Rx2 DMA1_Stream5

#define DMA1_Stream3_Tx3 DMA1_Stream3
#define DMA1_Stream1_Rx3 DMA1_Stream1

#define DMA1_Stream4_Tx4 DMA1_Stream4
#define DMA1_Stream2_Rx4 DMA1_Stream2

#define DMA1_Stream7_Tx5 DMA1_Stream7
#define DMA1_Stream0_Rx5 DMA1_Stream0

#define DMA2_Stream6_Tx6 DMA2_Stream6
#define DMA2_Stream1_Rx6 DMA2_Stream1
//
//

//串口1数据
uint8_t g_RxBuffer1[UART_BUF_SIZE1];  //接收缓冲1
uint8_t g_TxBuffer1[UART_BUF_SIZE1];  //发送缓冲1
uint8_t volatile  g_UartState1;   //UART1工作状态标记

//通讯1数据缓存
u8 Ctr_Rx_Buffer1[UART_BUF_SIZE1];    //通信用缓冲区
u8 Ctr_Tx_Buffer1[UART_BUF_SIZE1];    //通信用缓冲区
uint16_t Ctr_DataLength1;
 

///
///
void DMA_Configuration1(void);
void uart1_dma_init(uint16_t BaudRate)
{
    GPIO_InitTypeDef    GPIO_InitStructure;
    USART_InitTypeDef   USART_InitStructure;
    NVIC_InitTypeDef    NVIC_InitStructure;
	
    /* 1.使能PA口时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	
    /* 2.管脚映射 */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); /* GPIOA9复用为USART2 */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); /* GPIOA10复用为USART2 */

    /* 4.配置串口1的PA9和PA10管脚 */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);  /* TXIO */

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);  /* RXIO */

    /* 5.配置串口工作模式 */
		USART_DeInit(USART1);
    USART_InitStructure.USART_BaudRate            = BaudRate*100;//接电机控制
    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_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    /* 6.设置中断 */
    NVIC_InitStructure.NVIC_IRQChannel                   = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

		/* 7.配置串口中断 */
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//    USART_ITConfig(USART1, USART_IT_TC,   DISABLE);
//    USART_ITConfig(USART1, USART_IT_TXE,  DISABLE);
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);/* 使能IDLE中断 */
		/* 8.使能串口 */
    USART_Cmd(USART1, ENABLE);//使能串口
		
		/* 9.DMA配置*/
		DMA_Configuration1();
		
		 g_UartState1 = UART_IDLE1;
}

///
//*********************串口1DMA设置********************//
//#define DMA2_Stream7_Tx1 DMA2_Stream7
//#define DMA2_Stream2_Rx1 DMA2_Stream2
//uint8_t g_RxBuffer1[UART_BUF_SIZE1];  //接收缓冲1
//uint8_t g_TxBuffer1[UART_BUF_SIZE1];  //发送缓冲1
//uint8_t volatile  g_UartState1;   //UART1工作状态标记

void DMA_Configuration1(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    /* 1.使能DMA2时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
	

    /* 2.配置使用DMA发送数据 */
    DMA_DeInit(DMA2_Stream7_Tx1);

    DMA_InitStructure.DMA_Channel             = DMA_Channel_4;               /* 配置DMA通道 */
    DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t)(&(USART1->DR));   /* 目的 */
    DMA_InitStructure.DMA_Memory0BaseAddr     = (uint32_t)g_TxBuffer1;             /* 源 雷达的数据*/
    DMA_InitStructure.DMA_DIR                 = DMA_DIR_MemoryToPeripheral;    /* 方向 */
    DMA_InitStructure.DMA_BufferSize          = UART_BUF_SIZE1;                   					 /* 长度 */
    DMA_InitStructure.DMA_PeripheralInc       = DMA_PeripheralInc_Disable;    /* 外设地址是否自增 */
    DMA_InitStructure.DMA_MemoryInc           = DMA_MemoryInc_Enable;         /* 内存地址是否自增 */
    DMA_InitStructure.DMA_PeripheralDataSize  = DMA_MemoryDataSize_Byte;      /* 目的数据带宽 */
    DMA_InitStructure.DMA_MemoryDataSize      = DMA_MemoryDataSize_Byte;      /* 源数据宽度 */
    DMA_InitStructure.DMA_Mode                = DMA_Mode_Normal;              /* 单次传输模式/循环传输模式 */
    DMA_InitStructure.DMA_Priority            = DMA_Priority_VeryHigh;             /* DMA优先级 */
    DMA_InitStructure.DMA_FIFOMode            = DMA_FIFOMode_Disable;          /* FIFO模式/直接模式 */
    DMA_InitStructure.DMA_FIFOThreshold       = DMA_FIFOThreshold_HalfFull; /* FIFO大小 */
    DMA_InitStructure.DMA_MemoryBurst         = DMA_MemoryBurst_Single;       /* 单次传输 */
    DMA_InitStructure.DMA_PeripheralBurst     = DMA_PeripheralBurst_Single;

    /* 3. 配置DMA */
    DMA_Init(DMA2_Stream7_Tx1, &DMA_InitStructure);
    /* 4.使能DMA中断 */
//    DMA_ITConfig(DMA2_Stream7_Tx1, DMA_IT_TC, ENABLE);
//		DMA_ITConfig(DMA2_Stream7_Tx1, DMA_IT_TE, ENABLE);
    /* 5.使能串口的DMA发送接口 */
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    /* 7.不使能DMA */
    DMA_Cmd(DMA2_Stream7_Tx1, DISABLE);
		

    /* 2.配置使用DMA接收数据 */
    DMA_DeInit(DMA2_Stream2_Rx1);

    DMA_InitStructure.DMA_Channel             = DMA_Channel_4;               	/* 配置DMA通道 */
    DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t)(&(USART1->DR));   	/* 目的 */
    DMA_InitStructure.DMA_Memory0BaseAddr     = (uint32_t)g_RxBuffer1;   /* 源 雷达的数据*/
    DMA_InitStructure.DMA_DIR                 = DMA_DIR_PeripheralToMemory;   /* 方向 */
    DMA_InitStructure.DMA_BufferSize          = UART_BUF_SIZE3;             /* 长度 */
    DMA_InitStructure.DMA_PeripheralInc       = DMA_PeripheralInc_Disable;    /* 外设地址是否自增 */
    DMA_InitStructure.DMA_MemoryInc           = DMA_MemoryInc_Enable;         /* 内存地址是否自增 */
    DMA_InitStructure.DMA_PeripheralDataSize  = DMA_MemoryDataSize_Byte;      /* 目的数据带宽 */
    DMA_InitStructure.DMA_MemoryDataSize      = DMA_MemoryDataSize_Byte;      /* 源数据宽度 */
    DMA_InitStructure.DMA_Mode                = DMA_Mode_Normal;              /* 单次传输模式/循环传输模式 */
    DMA_InitStructure.DMA_Priority            = DMA_Priority_High;             /* DMA优先级 */
    DMA_InitStructure.DMA_FIFOMode            = DMA_FIFOMode_Disable;          /* FIFO模式/直接模式 */
    DMA_InitStructure.DMA_FIFOThreshold       = DMA_FIFOThreshold_HalfFull;    /* FIFO大小 */
    DMA_InitStructure.DMA_MemoryBurst         = DMA_MemoryBurst_Single;        /* 单次传输 */
    DMA_InitStructure.DMA_PeripheralBurst     = DMA_PeripheralBurst_Single;

    /* 3. 配置DMA */
    DMA_Init(DMA2_Stream2_Rx1, &DMA_InitStructure);
    /* 4.使能DMA中断 */
//    DMA_ITConfig(DMA2_Stream2_Rx1, DMA_IT_TC, ENABLE);
//		DMA_ITConfig(DMA2_Stream2_Rx1, DMA_IT_TE, ENABLE);
//		DMA_ITConfig(DMA2_Stream2_Rx1, DMA_IT_HT, ENABLE);
    /* 5.使能串口的DMA发送接口 */
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
    /* 7.使能DMA */
    DMA_Cmd(DMA2_Stream2_Rx1, ENABLE);
}

//
//
extern u32 wcntCK_uartrx_over[6];//接收超时
extern u8  uflagCK_uartrx_over[6];//接收超时
u8  uflagCK_Ctr_Modbus[6];//接收超时

void Ctr_Modbus1(void);
//空闲中断
void USART1_IRQHandler(void)
{
    u16 data, i;

    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
			//读SR后读DR清除Idle,下面2行代码不能少,也不能用USART_ClearITPendingBit(USART1, USART_IT_IDLE);来代替
			data = USART1->SR;
			data = USART1->DR;
			
			//关闭DMA,防止处理其间有数据
      DMA_Cmd(DMA2_Stream2_Rx1, DISABLE); //关闭DMA,防止处理其间有数据
			//读数据
			Ctr_DataLength1 =UART_BUF_SIZE1 - DMA_GetCurrDataCounter(DMA2_Stream2_Rx1);
      //处理数据
			if (Ctr_DataLength1 > 0)
      {
            for (i = 0; i < Ctr_DataLength1; i++) //将数据送DMA存储地址
            {
                Ctr_Rx_Buffer1[i] = g_RxBuffer1[i];
            }
      }
			//重新开始接受DMA数据
			DMA_Cmd(DMA2_Stream2_Rx1, DISABLE); //改变datasize前先要禁止通道工作
			DMA_ClearFlag(DMA2_Stream2_Rx1, DMA_FLAG_TCIF2 | DMA_FLAG_FEIF2 | DMA_FLAG_DMEIF2 | DMA_FLAG_TEIF2 | DMA_FLAG_HTIF2); //清除DMA2_Steam7传输完成标志 
			DMA_SetCurrDataCounter(DMA2_Stream2_Rx1, UART_BUF_SIZE1);
			DMA_Cmd(DMA2_Stream2_Rx1, ENABLE);
			
			g_UartState1 = UART_RECV1;
			
//			Ctr_Modbus1();//控制通讯 放入主定时循环里
		}

}

//
//#define DMA2_Stream7_Tx1 DMA2_Stream7
//#define DMA2_Stream2_Rx1 DMA2_Stream2
//发送完成中断
void DMA2_Stream7_IRQHandler(void)
{
    u16 data, i;
    //清除标志
    if(DMA_GetFlagStatus(DMA2_Stream7_Tx1, DMA_FLAG_TCIF7) != RESET) //等待DMA2_Steam7传输完成
    {
        DMA_ClearFlag(DMA2_Stream7_Tx1, DMA_FLAG_TCIF7); //清除DMA2_Steam7传输完成标志
    }
}

//接收通道中断
void DMA2_Stream2_IRQHandler(void)
{
    u16 data, i;
    //清除标志
    if(DMA_GetFlagStatus(DMA2_Stream2_Rx1, DMA_FLAG_TCIF2) != RESET) //等待DMA2_Steam7传输完成
    {
        DMA_ClearFlag(DMA2_Stream2_Rx1, DMA_FLAG_TCIF2); //清除DMA2_Steam7传输完成标志
    }
}


//
//dma数据发送
//#define DMA2_Stream7_Tx1 DMA2_Stream7
//#define DMA2_Stream2_Rx1 DMA2_Stream2
void uart1_send_dma(uint8_t *buf, uint8_t len)
{
    DMA_InitTypeDef DMA_InitStructure;
    /* 1.使能DMA1时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
	
  	/* 2.配置使用DMA发送数据 */
    DMA_DeInit(DMA2_Stream7_Tx1);
    DMA_InitStructure.DMA_Channel             = DMA_Channel_4;               /* 配置DMA通道 */
    DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t)(&(USART1->DR));   /* 目的 */
    DMA_InitStructure.DMA_Memory0BaseAddr     = (uint32_t)buf;//数据            /* 源 雷达的数据*/
    DMA_InitStructure.DMA_DIR                 = DMA_DIR_MemoryToPeripheral;    /* 方向 */
    DMA_InitStructure.DMA_BufferSize          = len;//长度          					 /* 长度 */
    DMA_InitStructure.DMA_PeripheralInc       = DMA_PeripheralInc_Disable;    /* 外设地址是否自增 */
    DMA_InitStructure.DMA_MemoryInc           = DMA_MemoryInc_Enable;         /* 内存地址是否自增 */
    DMA_InitStructure.DMA_PeripheralDataSize  = DMA_MemoryDataSize_Byte;      /* 目的数据带宽 */
    DMA_InitStructure.DMA_MemoryDataSize      = DMA_MemoryDataSize_Byte;      /* 源数据宽度 */
    DMA_InitStructure.DMA_Mode                = DMA_Mode_Normal;              /* 单次传输模式/循环传输模式 */
    DMA_InitStructure.DMA_Priority            = DMA_Priority_High;             /* DMA优先级 */
    DMA_InitStructure.DMA_FIFOMode            = DMA_FIFOMode_Disable;          /* FIFO模式/直接模式 */
    DMA_InitStructure.DMA_FIFOThreshold       = DMA_FIFOThreshold_HalfFull; /* FIFO大小 */
    DMA_InitStructure.DMA_MemoryBurst         = DMA_MemoryBurst_Single;       /* 单次传输 */
    DMA_InitStructure.DMA_PeripheralBurst     = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream7_Tx1, &DMA_InitStructure);
		
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    DMA_ITConfig(DMA2_Stream7_Tx1, DMA_IT_TC, ENABLE);
    DMA_Cmd(DMA2_Stream7_Tx1, ENABLE);
}

//
//DMA发送多字节
//开启一次DMA传输
//数据:g_TxBuffer1[i]
//#define DMA2_Stream7_Tx1 DMA2_Stream7
//#define DMA2_Stream2_Rx1 DMA2_Stream2
void uart1_dma_tx(void)
{
	u8 len=50;
	u8 crc=0x33;
	u8 i;
	//******数据发送位******
	//包头
	g_TxBuffer1[0]=0xBB;
	g_TxBuffer1[1]=0x66;
	g_TxBuffer1[2]=0x15;
	g_TxBuffer1[3]=len;
	//数据区
	//包尾
	g_TxBuffer1[49]=crc;
	//******数据发送******
	uart1_send_dma(g_TxBuffer1, len);
}

//
//
void Ctr_Modbus1(void)
{
    u8 i;
    u8 Command = 0;
	  u8 board=0;
	  u8 Cmd_length=0;
	
    if (g_UartState1 == UART_RECV1) //接收完成
    {
        i = Ctr_DataLength1;//10长度
				/*******包头*****/
        if( (Ctr_Rx_Buffer1[0] != 0xBB) || (Ctr_Rx_Buffer1[1] != 0x66))
            return ;
				/*******板子连接类型*****/
				board=Ctr_Rx_Buffer1[2];//长度
				/*******cmd*****/
				Command =  Ctr_Rx_Buffer1[3];//指令
				Cmd_length=Ctr_Rx_Buffer1[4];//长度
        switch (Command)
        {
				
				}
		}
		g_UartState1 = UART_IDLE1;
}

 

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值