智能车制作

 找回密码
 注册

扫一扫,访问微社区

QQ登录

只需一步,快速开始

查看: 154|回复: 2

K66用eDMA通过UART发送数据

[复制链接]

1

主题

7

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
367
威望
199
贡献
112
兑换币
119
注册时间
2016-9-14
在线时间
28 小时
毕业学校
hit
发表于 2018-1-12 12:46:19 | 显示全部楼层 |阅读模式
//作者:哈工大智能车创新俱乐部
////主要依赖:MK66F18.h(CMSIS Peripheral Access Layer for MK66F18)
////描述:用DMA发送数据,减缓CPU的运行压力。


#define BAUD_RATE 115200
#define UART_WITH_DMA uart1
#define DMA_UARTn_Tx DMA_UART1_Tx

#define DMA_CHANNEL_in_GROUP1 17 //请用16到31通道
//选group1 配置group1的优先级低于group 0(摄像头驱动使用g0)

#define default_transmittion_size 50
#define default_minor_loop_counter                      default_transmittion_size
#define default_dma_address_go_back_when_finish         default_transmittion_size

uint8 sendbuff[1024]="Empty eDMA-UART send buff,wanna put some thing in here?\n";
extern  UART_Type * uart[5];
void uart_init_with_dma()
{

  uart_init (UART_WITH_DMA, BAUD_RATE);  
  uart[UART_WITH_DMA]->C2 |=
                     (0
                        | UART_C2_TE_MASK                       //发送使能
                        | UART_C2_RE_MASK                       //接收使能
                        | UART_C2_TIE_MASK                    //发送中断或DMA传输请求使能
                     );
  uart[UART_WITH_DMA]->C2 &=~UART_C2_TCIE_MASK;
  uart[UART_WITH_DMA]->C5 |=UART_C5_TDMAS_MASK;




  SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;                       //时钟
  SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK;                    //时钟
  DMAMUX0->CHCFG[DMA_CHANNEL_in_GROUP1] = (0
                            | DMAMUX_CHCFG_ENBL_MASK                      // Enable routing of DMA request
                            | DMAMUX_CHCFG_SOURCE(DMA_UARTn_Tx)  // 通道触发传输源:   
                       );

  DMA0->CR  |= DMA_CR_GRP0PRI_MASK ;//CR_GRP0PRI=1      //设0组有高优先级
  DMA0->CR  &=~ DMA_CR_GRP1PRI_MASK ;//CR_GRP1PRI=0     //设1组有低优先级
  //实际上用DMA1,即16到31通道
  //PS:DMA0是0到15通道

  DMA0->TCD[DMA_CHANNEL_in_GROUP1].SADDR =(uint32)(void *)(sendbuff) ;
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].DADDR =(uint32)(&(uart[UART_WITH_DMA]->D));

  DMA0->TCD[DMA_CHANNEL_in_GROUP1].NBYTES_MLNO = DMA_NBYTES_MLNO_NBYTES(1);////需要发送的数据,最好是4的整数倍.
  //UART准备好后 触发一次minor loop  每个minor loop 只能把一个字节送入传输用的寄存器

  DMA0->TCD[DMA_CHANNEL_in_GROUP1].SLAST= - default_dma_address_go_back_when_finish;  ////大循环结束后,源地址改变量。最好是4的整数倍,等于上面
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].DLAST_SGA = 0;                         ////大循环结束后,目标地址改变量。最好是4的整数倍,等于上面
  //UART情况 地址不变

  DMA0->TCD[DMA_CHANNEL_in_GROUP1].SOFF = 1;                //读取一次地址后,偏移量,与DMA_ATTR_SSIZE有关?
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].DOFF = 0;                //写一次地址后,  偏移量,与DMA_ATTR_DSIZE有关?

  DMA0->TCD[DMA_CHANNEL_in_GROUP1].ATTR = (
                                                DMA_ATTR_SSIZE(0)
                                              | DMA_ATTR_DSIZE(0)  
                                              | DMA_ATTR_SMOD(0)               //Source address modulo feature is disabled
                                              | DMA_ATTR_DMOD(0)               
                                              |0        
                                          );

  DMA0->TCD[DMA_CHANNEL_in_GROUP1].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(default_minor_loop_counter);//minor loop小循环计数
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(default_minor_loop_counter);//需要与上面的值实质相等
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].CSR = 0;
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].CSR = (0
                             | DMA_CSR_BWC(3)//带宽控制,每读一次,eDMA 引擎停止 8 个周期
                             //DMA冷却时间(0不停止;1保留;2停止4周期;3停止8周期)
//取消注释,解除反复发送     // | DMA_CSR_DREQ_MASK            //主循环结束后停止硬件请求  /* major_loop递减为0时自动关闭DMA,即只进行一次DMA传输 */
                             | DMA_CSR_INTMAJOR_MASK        //主循环结束后产生中断
                            );
  //DMA0->CR &= ~DMA_CR_EMLM_MASK;//Minor Loop Mapping Disabled.//default disabled already



// DMA0->TCD[DMA_CHANNEL_in_GROUP1].CSR |= DMA_CSR_START(1);
  DMA0->ERQ &=~ (DMA_ERQ_ERQ0_MASK<<( DMA_CHANNEL_in_GROUP1 ));

  uint8 test = DMA0->DCHPRI16;

}
/*
*说明:开始循环传输,开始之后不用管。。
*传输size个字节
*地址为上面的sendbuff[1024]
*/
void uart_dma_start_Nostop(uint32 size)
{
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(size);//minor loop小循环计数
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(size);//需要与上面的值实质相等
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].SLAST= - size;  ////大循环结束后,源地址改变量
  DMA0-> ERQ |= (1 << DMA_CHANNEL_in_GROUP1);      //开始循环传输
}
/*
*说明:开始循环传输,开始之后不用管。。
*传输size个字节
*传输某地址开始的size个字节
*/
void uart_dma_start_Nostop_plus_BuffAddress(void *t,uint32 size)
{
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].SADDR =(uint32)t;
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(size);//minor loop小循环计数
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(size);//需要与上面的值实质相等
  DMA0->TCD[DMA_CHANNEL_in_GROUP1].SLAST= - size;  ////大循环结束后,源地址改变量
  DMA0-> ERQ |= (1 << DMA_CHANNEL_in_GROUP1);      //开始循环传输
}

void uart_dma_stop()
{
    DMA0->ERQ &=~ (DMA_ERQ_ERQ0_MASK<<( DMA_CHANNEL_in_GROUP1 ));
}


回复

使用道具 举报

44

主题

4420

帖子

3

精华

顶级版主

北京科技大学智能汽车队公共主页管理员

Rank: 11Rank: 11Rank: 11Rank: 11

积分
45177

特殊贡献奖章资源大师奖章论坛骨干奖章推广达人奖章优秀版主奖章热心会员奖章论坛元老奖章在线王奖章活跃会员奖章优秀会员奖章

威望
15059
贡献
10946
兑换币
274
注册时间
2010-7-22
在线时间
9587 小时
发表于 2018-1-12 18:12:24 | 显示全部楼层
看手册1905页

你有没有发现uart0和uart1有8字节的FIFO?所以只需要打开FIFO功能然后一次性传8个数据进去就行了
回复 支持 反对

使用道具 举报

3

主题

19

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2005
威望
1012
贡献
649
兑换币
723
注册时间
2015-10-25
在线时间
172 小时
毕业学校
中南大学
发表于 7 天前 | 显示全部楼层
aytc100 发表于 2018-1-12 18:12
看手册1905页

你有没有发现uart0和uart1有8字节的FIFO?所以只需要打开FIFO功能然后一次性传8个数据进去 ...

8字节可能不太够,我们一次要发600字节,开3M波特率
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 京ICP备14023231号-8

GMT+8, 2018-1-22 00:32 , Processed in 0.113753 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表