前言:
本来打算这次发蓝牙低功耗部分的测试记录,但是由于关于UART部分有些许的问题,所以还是先发这篇吧,请各个大佬指导一下!
一:介绍
B91开发套件的主控芯片有两组UART端口:UART0和UART1;这次测试的是UART0的DMA功能进行接受和发送;
UART引脚分布如下图:
二:程序
/********************************************************************************************************
* [url=home.php?mod=space&uid=1307177]@File[/url] app_dma.c
*
* [url=home.php?mod=space&uid=159083]@brief[/url] This is the source file for B91m
*
* [url=home.php?mod=space&uid=1315547]@author[/url] Driver Group
* [url=home.php?mod=space&uid=311857]@date[/url] 2019
*
* @par Copyright (c) 2019, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*******************************************************************************************************/
#include "app_config.h"
#include <stdio.h>
#define UART_MASTER_DEVICE 1
#define UART_SLAVE_DEVICE 2
#define UART_DEVICE UART_MASTER_DEVICE
#define UART_DMA_CHANNEL_RX DMA2
#define UART_DMA_CHANNEL_TX DMA3
#define BUFF_DATA_LEN 1024
#define DMA_REV_LEN_LESS_MAX 1 //b91 and b92 are optional
#define DMA_REV_LEN_MAX 2 //only b92 can choose
#define DMA_REV_LEN_TYPE 1
#define DMA_REV_LEN BUFF_DATA_LEN
volatile unsigned char tx_byte_buff[16] __attribute__((aligned(4))) ={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
volatile unsigned char rec_buff[BUFF_DATA_LEN] __attribute__((aligned(4))) = {0};
volatile unsigned char rev_data_len=0;
/*
功能:初始化4个指示灯,串口0(TX:PB2;RX:PB3)
*/
void user_init()
{
unsigned short div;
unsigned char bwpc;
gpio_function_en(LED1|LED2|LED3|LED4);
gpio_output_en(LED1|LED2|LED3|LED4); //enable output
gpio_input_dis(LED1|LED2|LED3|LED4); //disable input
uart_reset(UART0);//串口复位
uart_set_pin(UART0_TX_PIN,UART0_RX_PIN);//串口引脚选择
uart_cal_div_and_bwpc(115200, sys_clk.pclk*1000*1000, &div, &bwpc);//根据输⼊的波特率和系统时钟计算出最佳的时钟分频数div 和位宽bwpc
uart_set_rx_timeout(UART0, bwpc, 12, UART_BW_MUL2);//设置UART_BW_MUL2:接受2个字符超时时间
uart_init(UART0, div, bwpc, UART_PARITY_NONE, UART_STOP_BIT_ONE);//初始化检验位,停止位.....
uart_set_tx_dma_config(UART0, UART_DMA_CHANNEL_TX);//设置发送DMA通道
uart_set_rx_dma_config(UART0, UART_DMA_CHANNEL_RX);//设置接受DMA通道
uart_clr_tx_done(UART0);//将TX_DONE信号置0,否则会⼀直进中断
uart_set_irq_mask(UART0, UART_RXDONE_MASK);//使用TX_DONE中断,设置mask
uart_set_irq_mask(UART0, UART_TXDONE_MASK);//使用RX_DONE中断,设置mask
plic_interrupt_enable(IRQ19_UART0);//使能UART0的中断
core_interrupt_enable();//开中断
uart_receive_dma(UART0, (unsigned char*)rec_buff,DMA_REV_LEN);
}
void main_loop (void)
{
gpio_toggle(LED1);
delay_ms(1000);
}
/*
功能:中断回调
*/
_attribute_ram_code_sec_ void uart0_irq_handler(void)
{
if(uart_get_irq_status(UART0,UART_TXDONE)){
uart_clr_tx_done(UART0);
}
if(uart_get_irq_status(UART0,UART_RXDONE)){
gpio_toggle(LED2|LED3|LED4);
if((uart_get_irq_status(UART0,UART_RX_ERR))){//UART接受出错中断
printf(">>> UART_RX_ERR! <<<\r\n");
uart_clr_irq_status(UART0,UART_CLR_RX);
}
rev_data_len = uart_get_dma_rev_data_len(UART0,UART_DMA_CHANNEL_RX);//获取DMA接受的数据长度
printf("rev_data_len = %d\r\n",rev_data_len);
uart_clr_irq_status(UART0,UART_CLR_RX);//清除中断标志
//DMA access memory needs to be aligned according to word.
uart_receive_dma(UART0, (unsigned char*)rec_buff,DMA_REV_LEN);
uart_send_dma(UART0, (unsigned char*)rec_buff, rev_data_len);
}
}
三:现象
1)正常现象:成功接收到数据并回传以及接受数据的长度正确!
WeChat_20221007211142
2)非正常现象:数据存放数组长度为1024,且程序中uart_send_dma函数的数据长度参数同样为1024;
当要接受的数据小于256个字节时,数据正常回传,且数据长度正确;
当要接受的数据超过256个字节时,接受的数据长度自动清零;
当要接受的数据大于256个字节时,数据回传不正常,且数据长度=实发数据长度+换行符-256;
当然,也有可能是自己的设置不当才导致的上述问题出现,望各个大佬指点!
四:其他
在UART使用过程中还发现两个函数与驱动手册不一致,如下:
1)程序中使用的uart_set_rx_timeout函数,在《泰凌驱动SDK开发手册》中找不到,但是有uart_set_dma_rx_timeout函数,两者参数一致;
2)在《泰凌驱动SDK开发手册》中:5.3.1处描述打开中断使用的是core_enable_interrupt()函数;但是在5.3.3处打开中断就是core_interrupt_enable()函数了,程序中也使用的是core_interrupt_enable()函数;
综上:上边提到的两个问题不知道是因为下载的驱动手册太久远的原因,还是因为就是写错没审核了;
还是希望厂家多放出一些审核过的资料以及论坛和QQ群里的技术支持能够更及时一些!