TLSR8258——串口DMA通信功能不带数据流控

TLSR8258——串口DMA通信功能

官方串口简介摘要:

官方TLSR8258串口相关说明
TLSR8258F1KET48A嵌入UART(通用异步接收机/发射机),通过UART TX和RX接口实现全双工传输和接收。TX和RX接口均为4层FIFO(先进先出)接口。

通过RTS和CTS支持硬件流控制。

UART模块还支持ISO7816协议,以实现与ISO/IEC 7816集成电路卡,特别是智能卡的通信。在这种模式下,通过共享的7816_TRX接口支持半双工通信(发送或接收)。

UART支持DMA模式,可以大大简化数据传输和接收过程。此外,DMA和MCU之间的并行性可以提高程序的效率。要使用DMA模式,除了相关配置外,发送的数据结构必须符合以下特定要求:

定义的发送或接收缓冲区需要4字节对齐,前4个字节是传输的数据包的长度。
DMA模式下Tx和Rx缓冲区格式的框图如下:

Len[0]Len[1]Len[2]Len[3]DATA[0]DATA[1]DATA[2]

串口TX和RX引脚表

TXRX
PA2PA0
PB1PB0
PC2PC3
PD0PC5
PD3PB7
PD7PD6

本工程使用的引脚是RX->B0和TX->B1。

注意:
串口是DMA方式接收和发送,当连续发送多包数据时接收缓冲区是将多包数据一块接收,所以在解析接收数据时应对多包数据进行拆包处理后再进行逐一数据包发送。

串口函数 user_uart.c

/*
 * user_uart.c
 *
 *  Created on: 2023-10-13
 *      Author: ZJ
 */
#include "user_uart.h"

__attribute__((aligned(4))) unsigned char UART_RX_Buff[RX_Buff_Len] = {0};
__attribute__((aligned(4))) unsigned char UART_TX_Buff[RX_Buff_Len] = {0};

SUart_data_struct  Uart_data;
//串口接收数据缓冲区
fifo_struct   UART_RX_FIFO = {0};
//串口临时缓存区
frame_data_struct Uart_Rx_Data_Temp;
/**
 * @brief 配置串口和射频结构体参数
 */
void Config_Uart_RF_parama(void)
{
	memset(Uart_data.Rx_data,0,UART_DATA_LEN);
	memset(Uart_data.Tx_Data,0,UART_DATA_LEN);
	memset(Uart_data.buff,0,UART_DATA_LEN);
}


/**
 * @brief 串口初始化
 */
void Uart_Init(void)
{
	//注意:在进行任何其他uart初始化之前,必须先设置dma addr!
	uart_recbuff_init( (unsigned char *)UART_RX_Buff, sizeof(UART_RX_Buff));
	//设置 uart tx/rx pin
	uart_gpio_set(UART_TX_PIN, UART_RX_PIN);
	//每次使用UART时,最好都先调用复位函数,可以避免之前使用UART的操作对本次使用产生影响。
	uart_reset();
	//设置波特率
	uart_init_baudrate(115200,CLOCK_SYS_CLOCK_HZ,PARITY_NONE, STOP_BIT_ONE);
	//开启TX RX的DMA功能
	uart_dma_enable(1, 1);
	// uart_rx use dma_rx irq
	irq_enable_type(FLD_IRQ_DMA_EN);
	//uart Rx dma irq enable
	dma_chn_irq_enable(FLD_DMA_CHN_UART_RX, 1);
	//uart Tx dma irq enable
	uart_mask_tx_done_irq_enable();
	// 打开uart_errormask,当停止位错误或奇偶校验错误时,它将进入errorinterrupt。
	uart_mask_error_irq_enable();
	// uart_tx use uart_txdone irq
	irq_enable_type(FLD_IRQ_UART_EN);
	irq_enable();
}


/*
 * @brief:将串口DMA缓冲区中数据搬移
 * */
fifo_status_enum fifo_push(uint8_t *uart_rx_buff,fifo_struct *fifo_ptr)
{
	if (fifo_ptr->buff_size >= FIFO_SIZE)
	{
		/* 缓存帧已满  */
		return FIFO_FAILURE;
	}

	memcpy((void *)fifo_ptr->frame_repo[fifo_ptr->write_index].data,uart_rx_buff,uart_rx_buff[0]+4);
	fifo_ptr->frame_repo[fifo_ptr->write_index].length = uart_rx_buff[0]+4;

	/* 缓存帧数量增加1 */
	fifo_ptr->buff_size++;

	/* 缓存写入索引向前加1 */
	fifo_ptr->write_index =  (fifo_ptr->write_index + 1) % FIFO_SIZE;

	return FIFO_SUCCESS;
}

/*
 * @brief:将串口DMA缓冲区中数据提取使用
 * */
fifo_status_enum fifo_pop(frame_data_struct *frame_pop, fifo_struct *fifo_ptr)
{
    if (fifo_ptr->buff_size == 0)
    {
        /* 没有缓存的帧 */
        return FIFO_FAILURE;
    }

    frame_pop->length = fifo_ptr->frame_repo[fifo_ptr->read_index].length;
    memcpy((void *)frame_pop->data, (void *)fifo_ptr->frame_repo[fifo_ptr->read_index].data, fifo_ptr->frame_repo[fifo_ptr->read_index].length);

    /* 缓存帧数量减少1 */
    fifo_ptr->buff_size--;
    /* 更新读索引 */
    fifo_ptr->read_index = (fifo_ptr->read_index + 1) % FIFO_SIZE;

    return FIFO_SUCCESS;
}

/*
 * @brief:串口发送数据
 * */
void UARTXSend(PUart_data_struct Uart_data,uint8_t lenth)
{
	//TX DMA发送数据长度
	UART_TX_Buff[0] = lenth;
	//TX 数据搬移
	memcpy(&UART_TX_Buff[4],&Uart_data->Tx_Data[0],lenth);
	uart_send_dma((unsigned char *)UART_TX_Buff);
}

/**
 * @brief 串口数据处理
 * 将接收到的数据发送出来
 */
void Uart_Conduct(PUart_data_struct Uart_data)
{
	uint8_t i;
	//判断串口DMA缓冲区是否有数据缓存
	if(FIFO_SUCCESS == fifo_pop(&Uart_Rx_Data_Temp, &UART_RX_FIFO))
	{
		//拆分串口DMA接收数据包,判断缓冲区有几包数据帧
		if((Uart_Rx_Data_Temp.data[6]+(Uart_Rx_Data_Temp.data[7]<<8))+4 == Uart_Rx_Data_Temp.length-4)
		{
			memcpy(&Uart_data->Tx_Data[0],&Uart_Rx_Data_Temp.data[4],Uart_Rx_Data_Temp.length-4);
			UARTXSend(Uart_data,Uart_Rx_Data_Temp.length-4);
		}
		else
		{
			//多包数据拆分处理
			for(i = 4;i <= Uart_Rx_Data_Temp.length;i++)
			{
				if(Uart_Rx_Data_Temp.data[i] == 0xCD && Uart_Rx_Data_Temp.data[i+1] == 0x00)
				{
					memcpy(&Uart_data->Tx_Data[0],&Uart_Rx_Data_Temp.data[i],(Uart_Rx_Data_Temp.data[i+2]+(Uart_Rx_Data_Temp.data[i+3]<<8))+4);
					UARTXSend(Uart_data,(Uart_Rx_Data_Temp.data[i+2]+(Uart_Rx_Data_Temp.data[i+3]<<8))+4);
					sleep_ms(200);
				}
			}
		}
	}
	else
	{
		printf("串口未接收到数据......");
		sleep_ms(1000);
	}
}

串口函数 user_uart.h

/*
 * user_uart.h
 *
 *  Created on: 2023-10-13
 *      Author: zhangjian
 */

#ifndef USER_UART_H_
#define USER_UART_H_

#include "app_config.h"
#include "types.h"

/************************ 宏定义声明*********************************/
#define UART_DATA_LEN    150     //串口通信长度

#define UART_TX_PIN				UART_TX_PB1
#define UART_RX_PIN				UART_RX_PB0

#define RX_Buff_Len  512
#define TX_Buff_Len  512

#define FIFO_SIZE    10
#define FRAME_SIZE   512

/************************ 结构体 声明*********************************/
typedef struct Uart     //读写器串口数据结构体
{
  uint8_t Rx_data[UART_DATA_LEN];   //串口接收结构体
  uint8_t Tx_Data[UART_DATA_LEN];   //串口发送结构体
  uint8_t lenth;                   //帧长度
  uint8_t buff[UART_DATA_LEN];
} *PUart_data_struct,SUart_data_struct;


typedef struct
{
	uint8_t              data[FRAME_SIZE];
    volatile uint16_t    length;
}frame_data_struct;


typedef struct
{
    volatile uint8_t      write_index;
    volatile uint8_t      read_index;
    volatile uint8_t      buff_size;
    frame_data_struct     frame_repo[FIFO_SIZE];
}fifo_struct;

/************************ 枚举 声明*********************************/
typedef enum
{
    FIFO_SUCCESS = 0,
    FIFO_FAILURE
}fifo_status_enum;

/************************ 重定义声明*********************************/
extern SUart_data_struct  Uart_data;
extern unsigned char UART_RX_Buff[RX_Buff_Len];
extern unsigned char UART_TX_Buff[RX_Buff_Len];
extern fifo_struct   UART_RX_FIFO;

/************************ 函数声明**********************************/
fifo_status_enum fifo_push(uint8_t *uart_rx_buff,fifo_struct *fifo_ptr);
fifo_status_enum fifo_pop(frame_data_struct *frame_pop, fifo_struct *fifo_ptr);

void Config_Uart_RF_parama(void);
void Uart_Init(void);
void Uart_Conduct(PUart_data_struct Uart_data);

#endif /* USER_UART_H_ */

主函数 main.c

#include "app_config.h"
#include "calibration.h"
#include "user_uart.h"

_attribute_ram_code_sec_noinline_ void irq_handler(void)
{
	if(reg_uart_status1 & FLD_UART_TX_DONE)
	{
		//gpio_toggle(LED2);
		uart_clr_tx_done();
	}

	if(dma_chn_irq_status_get() & FLD_DMA_CHN_UART_RX)
	{
		//uart_send_dma((unsigned char *)RX_Buff);
		//缓存搬移
		fifo_push((unsigned char *)UART_RX_Buff,&UART_RX_FIFO);
		dma_chn_irq_status_clr(FLD_DMA_CHN_UART_RX);
	}
	if(uart_is_parity_error())//when stop bit error or parity error.
	{
		uart_clear_parity_error();
	}
}
/**
 * @brief		This is main function
 * @param[in]	none
 * @return      none
 */
int main (void) {
	cpu_wakeup_init();
	//Note: This function must be called, otherwise an abnormal situation may occur.
	//Called immediately after cpu_wakeup_init, set in other positions, some calibration values may not take effect.
	user_read_flash_value_calib();
	gpio_init(0);
	clock_init(SYS_CLK);
	printf("测试开始\r\n");
	Config_Uart_RF_parama();
	Uart_Init();
	while (1)
	 {
	 	Uart_Conduct(&Uart_data);
	}
	return 0;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西瓜籽@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值