当前位置:首页 > 单片机 > 单片机
[导读]使用PDC进行数据的收发能减少CPU的开销。这次就使用PDC进行UART数据的接收与发送,同时,也利用TC也实现了PDC的接收超时。PDC是针对外设的DMA控制器。对比DMA控制器,它更为简便,与相应外设的结合也更为紧密。比如说

使用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的时钟,否则配置不生效。

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

12345678910111213/* 缓冲区 */#define BUF_SIZE 8uint8_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;

中断设置。PDC的中断是通过相应外设产生的,所以这里需要对UART的中断进行配置。

1234567/* 启用缓冲区满中断*/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);

将接收缓冲区的数据通过PDC发送出去,并开始下一次数据的接收。

12345678910111213141516/* 参数size: 表示接收缓冲区中需要发送的数据的长度 */voidTransferRxBufAndRec(intsize){/* 等待发送完成 */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;}

UART的中断处理函数。在中断时,只需调用上面的函数,将接收缓冲区的内容重新发送出去即可。

12345678voidUART0_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内没有数据接收,则强制开始数据的发送。

使能TC时钟,及GPIO设置。

123456PMC->PMC_PCER0 = (1 << ID_TC0);constuint32_t TIOB_PIN = PIO_PA1;PIOA->PIO_PDR = TIOB_PIN;PIOA->PIO_ABCDSR[0] |= TIOB_PIN;PIOA->PIO_ABCDSR[1] &= ~TIOB_PIN;

TC模式设置。

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

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

123456789gUseTc.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 /* 使能外部事件 */;

RC设置,以及TC启用。在RC比较后,计数器将暂停工作。在下次UART数据的接收时,TIOB引脚的信号会触发TC以重新开始计数。

123456789/* UART的PDC接收时等待超时时间 */#define UART_RX_WAIT_MS 500/* 设置RC */constuint32_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;

中断设置。TC中断的优先级比UART的要高。

12345678/* 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);

中断处理。中断处理中过程中禁用PDC数据的接收,以免丢失数据。

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


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭