使用PDC进行数据的收发能减少CPU的开销。这次就使用PDC进行UART数据的接收与发送,同时,也利用TC也实现了PDC的接收超时。

PDC是针对外设的DMA控制器。对比DMA控制器,它更为简便,与相应外设的结合也更为紧密。比如说,要配置PDC时,首先要启用相应的外设的时钟;同时PDC收发的状态是通过外设上的寄存器反映出来的;甚至中断也是通过相应外设产生的。

使用PDC时,只需设置好传输时内存的地址,以及传输长度,就可以在外设和内存之前进行数据传输了。而SAM4的PDC甚至还提供了一个类似FIFO的功能:可以在进行本次传输的同时指定下次传输时的地址和长度,然后在本次传输结束时开始下一次传输。

一、 实现思路

本次会使用两组缓冲区,分别用来数据的接收和发送。在接收数据完成后,就让PDC把这个缓冲区的数据发送出去,并且使用另一个缓冲区进行数据接收。

使用PDC发送数据较为简单,只需设置好需要发送的数据的地址和长度即可。

但是在使用PDC接收数据的时,如果未接收足够指定数目的数据,是不会产生中断的。在这里使用TC来进行PDC接收数据时的等待超时处理

UART的引脚在没有数据传输时,是一直保持在高电平状态的。即只在有数据传输时,才会有电平的切换。而TC可以使用外部信号进行触发以重置计数器。这样一来,就可以让UART在接收数据的同时,不断对TC的计数器进行重置。而在没有接收数据时,就会使得TC顺利步进到一个特定的值,从而产生一个中断。

二、 UART的PDC配置

UART和MCK的基本配置保持不变:MCK为120 MHz,UART波特率为11520 Hz。

在配置PDC时,需要确保已经开启了相应UART的时钟,否则配置不生效。

  1. 缓冲区和PDC的配置。配置完成,且启用UART的接收后,就可以进行数据的接收了。

    /* 缓冲区 */
    #define BUF_SIZE 8
    uint8_t BUF1[BUF_SIZE];
    uint8_t BUF2[BUF_SIZE];
    uint8_t* RX_BUF;/* 先设置好接收的BUF */
    RX_BUF = BUF1;
    PDC_UART0->PERIPH_RPR = RX_BUF;
    PDC_UART0->PERIPH_RCR = BUF_SIZE;/* 使能输入输出*/
    PDC_UART0->PERIPH_PTCR = PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN;
  2. 中断设置。PDC的中断是通过相应外设产生的,所以这里需要对UART的中断进行配置。

    /* 启用缓冲区满中断*/
    UART0->UART_IER = UART_IER_RXBUFF;
    /* 在NVIC中启用中断,将优先级设置为1*/
    NVIC_DisableIRQ(UART0_IRQn);
    NVIC_ClearPendingIRQ(UART0_IRQn);
    NVIC_SetPriority(UART0_IRQn, 1);
    NVIC_EnableIRQ(UART0_IRQn);
  3. 将接收缓冲区的数据通过PDC发送出去,并开始下一次数据的接收。

    /* 参数size: 表示接收缓冲区中需要发送的数据的长度 */
    void TransferRxBufAndRec(int size)
    {/* 等待发送完成 */while(!(UART0->UART_SR & UART_SR_TXBUFE));/* 通过PDC发送 */PDC_UART0->PERIPH_TPR = RX_BUF;PDC_UART0->PERIPH_TCR = size;/* 使用另一个缓冲区继续接收 */RX_BUF = (RX_BUF == BUF1) ? BUF2 : BUF1;PDC_UART0->PERIPH_RPR = RX_BUF;PDC_UART0->PERIPH_RCR = BUF_SIZE;
    }
  4. UART的中断处理函数。在中断时,只需调用上面的函数,将接收缓冲区的内容重新发送出去即可。

    void UART0_Handler(void)
    {/*判断是否是由“接收缓冲区满”引发的中断 */if (UART0->UART_SR & UART_SR_RXBUFF){TransferRxBufAndRec(BUF_SIZE);}
    }

这样配置完成后,删除上一节中UART收发数据的代码,即可完成数据的收发了。

三、 TC的配置

使用的通道为通道0:

#define gUseTc TC0->TC_CHANNEL[0]

使TC工作在波形输出模式下,将TIOB引脚(PA1)用做外部事件引脚,短接它和UART0接收引脚,即短接PA1和PA9引脚。在配置完成后,若500ms内没有数据接收,则强制开始数据的发送。

  1. 使能TC时钟,及GPIO设置。

    PMC->PMC_PCER0 = (1 << ID_TC0);const uint32_t TIOB_PIN = PIO_PA1;
    PIOA->PIO_PDR = TIOB_PIN;
    PIOA->PIO_ABCDSR[0] |= TIOB_PIN;
    PIOA->PIO_ABCDSR[1] &= ~TIOB_PIN;
  2. TC模式设置。

    利用TC的RC比较时产生的中断进行超时提醒,TIOB引脚电平的下降沿TC的触发。由于进行TC触发时也会开启时钟,所以在RC比较时暂停时钟。

    由于超时时间可能较长,且精度要求不高,让TC使用慢时钟SLCK就可以了。

    gUseTc.TC_CMR =TC_CMR_WAVE             /* 波形模式 */| TC_CMR_TCCLKS_TIMER_CLOCK5      /* 时钟5: SLCK */| TC_CMR_WAVSEL_UP_RC            /* 波形仅上升,且RC比较时触发 */| TC_CMR_CPCSTOP         /* RC 比较时自动停止时钟 */| TC_CMR_EEVT_TIOB            /* 设置为外部事件为TIOB */| TC_CMR_EEVTEDG_FALLING      /* 外部事件下降沿触发 */| TC_CMR_ENETRG          /* 使能外部事件   */;
  3. RC设置,以及TC启用。在RC比较后,计数器将暂停工作。在下次UART数据的接收时,TIOB引脚的信号会触发TC以重新开始计数。

    /* UART的PDC接收时等待超时时间 */
    #define UART_RX_WAIT_MS 500/* 设置RC */
    const uint32_t rc_v = CHIP_FREQ_SLCK_RC * UART_RX_WAIT_MS / 1000;
    gUseTc.TC_RC = TC_RC_RC(rc_v);/* 使能TC时钟,但不开始*/
    gUseTc.TC_CCR = TC_CCR_CLKEN;
  4. 中断设置。TC中断的优先级比UART的要高。

    /* RC 比较时产生中断 */
    gUseTc.TC_IER = TC_IER_CPCS;/* NVIC , 优先级设置为0 */
    NVIC_DisableIRQ(TC0_IRQn);
    NVIC_ClearPendingIRQ(TC0_IRQn);
    NVIC_SetPriority(TC0_IRQn, 0);
    NVIC_EnableIRQ(TC0_IRQn);
  5. 中断处理。中断处理中过程中禁用PDC数据的接收,以免丢失数据。

    void TC0_Handler(void)
    {uint32_t status = gUseTc.TC_SR;/* 判断中断是否为RC比较触发的 */if (status & TC_SR_CPCS){PDC_UART0->PERIPH_PTCR = PERIPH_PTCR_RXTDIS;/* 计算PDC中接收到的数据的大小 */const int rec_size = BUF_SIZE - (PDC_UART0->PERIPH_RCR);if (rec_size != 0){TransferRxBufAndRec(rec_size);}PDC_UART0->PERIPH_PTCR = PERIPH_PTCR_RXTEN;}
    }

转载于:https://www.cnblogs.com/h46incon/p/3438351.html

SAM4E单片机之旅——11、UART之PDC收发相关推荐

  1. SAM4E单片机之旅——10、UART与MCK之PLL

    为使用更更高的波特率,则需要更更高的外设时钟的频率.这个时候就需要用到锁相环(PLL)了.锁相环可以对输入的时钟进行分频.升频后进行输出.MCK可以使用的锁相环为PLLA,而PLLA的输入时钟为MAI ...

  2. SAM4E单片机之旅——13、LCD之ASF初步

    在Atmel Studio 6中,集成了Atmel Software Framework(ASF框架).通过它提供的库,可以很快速地完成新的项目. 这次的最终目标使用ASF在LCD上显示出文字&quo ...

  3. WCF后续之旅(11): 关于并发、回调的线程关联性(Thread Affinity)

    对于一般的多线程操作,比如异步地进行基于文件系统的IO操作:异步地调用Web Service:或者是异步地进行数据库访问等等,是和具体的线程无关的.也就是说,对于这些操作,任意创建一个新的线程来执行都 ...

  4. STM32单片机实现DMA+ADC+UART功能

    突然想测试一下STM32单片机ADC采样速率问题,按照常规方法,可以通过ADC采样,然后将采样值打印出来.但是这种方法在处理和打印数据的时候会占用很多时间,导致处理数据的时间超过了ADC的采样时间.于 ...

  5. STM32F103系列的单片机一共有11个定时器

    STM32F103系列的单片机一共有11个定时器,其中: 2个高级定时器 4个普通定时器 2个基本定时器 2个看门狗定时器 1个系统嘀嗒定时器 出去看门狗定时器和系统滴答定时器的八个定时器列表; 8个 ...

  6. Tiva单片机——简易示波器(UART串口屏)

    Tiva单片机--简易示波器(UART串口屏) 一.整体介绍 二.代码的分段解读 1.头函数 2.宏定义及变量定义 3.外设初始化 4.波形触发设计 5.电压标定设计 6.频率测定(最高到达1MHz) ...

  7. dac梯形波c语言编程,单片机项目第11章单片机与AD接口.ppt-资源下载在线文库www.lddoc.cn...

    单片机项目第11章 单片机与AD接口.ppt 第11章 单片机与AD接口,11.1 项目内容数字电压表的设计 11.2 程序设计 11.3 相关知识,11.1 项目内容数字电压表的设计,11.1.1 ...

  8. Linux 之旅 11:Linux 账号管理与 ACL 权限设置

    Linux 之旅 11:Linux 账号管理与 ACL 权限设置 Linux 的账号与用户组 使用者识别码:UID与GID 关于Linux的账号管理,有两个数字最为重要: UID:(User ID), ...

  9. 微雪树莓派PICO笔记——5. UART (异步收发传输器)

    文章目录 通讯协议 UART UART详解 RP2040 UART参数 UART流程图 函数详解 例程地址 码代码 通讯协议 MCU如果要说话需要约定一定的规则,这些规则,我们称为通信协议 常见的有U ...

  10. Python实战技巧(11)使用python收发邮件时需要的邮箱授权码如何获取

    Python实战技巧(1)Python字典类型数据如何递归地通过点'.'的方式访问 Python实战技巧(2)Python的pdb调试代码方法详解 Python实战技巧(3)多版本兼容安装部署(py2 ...

最新文章

  1. Axis2 -POJO
  2. 浅谈腾讯微博与新浪微博的优劣
  3. 【小白学习tensorflow教程】四、使用 tfhub中的模型EfficientDet-Lite2 进行对象检测
  4. ImageLoader must be init with configuration before using 错误解决方法
  5. mysql异常恢复工具_[MySQL异常恢复]mysql ibd文件恢复
  6. jxls向右循环为什么会间隔单元格_VBA中单元格的Offset属性,你是否能灵活的利用呢?...
  7. java8 Lambda Stream collect Collectors 常用实例
  8. NLP--- 将改变你未来沟通方式的7种NLP技术(第二部分)
  9. linux 系统命令总结之ubuntu 系列命令 持续更新中~
  10. Java jdk API 1.8英文版、中文版分享
  11. 生信技能04 - 生信分析所需致病SNP位点Excel文件制作教程
  12. outlook导出邮件(.msg)读取和解析
  13. php date函数 在哪里,PHP date函数
  14. 如果有一天我不更新博客了
  15. 联想Y400win10基础上在安装win7
  16. 天池竞赛员工离职预测训练赛
  17. 千寻位置NTRIP网络基准站
  18. 激光在大气中传输特性
  19. java小球左右_java小球碰撞窗体边缘来回反弹的代码
  20. 萤石春季发布会:4+N产品体系再升级EZVIZ Connect连接智能生活

热门文章

  1. 【js与jquery】导航下拉菜单效果
  2. 谈谈 Delphi 的类型与指针[2]
  3. 【转】js获取浏览器信息和客户端硬件信息
  4. 在linux命令行利用SecureCRT上传下载文件
  5. Spring整合- mongodb
  6. Nginx 的 server_names_hash_bucket_size 问题
  7. ES常用DSL语句(kibana常用语句)
  8. linux常用文件及作用总结(profile/.bashrc等)
  9. Dubbo本地伪装 Mock
  10. 如何把一个软件嵌入另一个软件_Notion可不只是一个笔记软件