智能车制作

标题: K66用eDMA通过UART发送数据 [打印本页]

作者: fuqingxu    时间: 2018-1-12 12:46
标题: K66用eDMA通过UART发送数据
//作者:哈工大智能车创新俱乐部
////主要依赖: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 ));
}




补充内容 (2018-7-18 23:30):
66
作者: aytc100    时间: 2018-1-12 18:12
看手册1905页

你有没有发现uart0和uart1有8字节的FIFO?所以只需要打开FIFO功能然后一次性传8个数据进去就行了
作者: jingjiAlex    时间: 2018-1-15 08:32
aytc100 发表于 2018-1-12 18:12
看手册1905页

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

8字节可能不太够,我们一次要发600字节,开3M波特率





欢迎光临 智能车制作 (http://111.231.132.190/) Powered by Discuz! X3.2