Ken,
如下是DAM CAN1 IF1发送数据, 请帮我查看寄存器配置是否出现问题?关于IFUEy寄存器 DATASHEET 好像没有说明?
/* USER CODE BEGIN (0) */
#include "rti.h"
#include "can.h"
#include "sys_dma.h"
/* USER CODE END */
/* Include Files */
#include "sys_common.h"
/* USER CODE BEGIN (1) */
#define D_SIZE 8
uint8 TX_DATA1[D_SIZE]={0x30,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8}; /* transmit buffer in sys ram */
uint8 TX_DATA2[D_SIZE]={0x30,0x03,14,15,16,17,18}; /* transmit buffer in sys ram */
uint8 TX_DATA3[D_SIZE]={21,22,23,24,25,26,27,28}; /* transmit buffer in sys ram */
uint8 RX_DATA1[D_SIZE]= {0}; /* receive buffer in sys ram */
uint8 RX_DATA2[D_SIZE]= {0}; /* receive buffer in sys ram */
uint8 RX_DATA3[D_SIZE]= {0};
/* USER CODE END */
/** @fn void main(void)
* @brief Application main function
* @note This function is empty by default.
*
* This function is called after startup.
* The user can use this function to implement the application.
*/
/* USER CODE BEGIN (2) */
uint32 DMAFlag=0x00;
uint32 DMA_Comp_Flag;
uint32 timer0 = 0;
uint32 CpuCount = 0;
uint8 senderFlag = 0;
g_dmaCTRL g_dmaCTRLPKT; /* dma control packet configuration stack */
void dmaConfigCtrlRxPacket(uint32 sadd,uint32 dadd,uint32 dsize);
/* USER CODE END */
void main(void)
{
/* USER CODE BEGIN (3) */
rtiInit();
rtiStartCounter(rtiCOUNTER_BLOCK0);
rtiDisableNotification(rtiNOTIFICATION_COMPARE0);
canInit();
_enable_IRQ();
canREG1->CTL |= (uint32)(1<<18); // enable DMA for IF2
dmaReqAssign(DMA_CH1, 8); // DMA Configuration and Enable DMA
dmaConfigCtrlRxPacket((uint32)(&TX_DATA1), (uint32)(&(canREG1->IF1DATx[0])), 1);
dmaSetCtrlPacket(DMA_CH1, g_dmaCTRLPKT); // setting dma control packets for transmit
dmaSetChEnable(DMA_CH1, DMA_HW);
dmaEnableInterrupt(DMA_CH1, FTC); // Enable Interrupt after reception of data
while(1)
{
CpuCount = canIsTxMessagePending(canREG1, canMESSAGE_BOX1);
}
/* USER CODE END */
}
/* USER CODE BEGIN (4) */
#pragma WEAK(rtiNotification)
void rtiNotification(uint32 notification)
{
/* enter user code between the USER CODE BEGIN and USER CODE END. */
/* USER CODE BEGIN (9) */
/* Reset the Flag */
timer0 ++;
}
void dmaConfigCtrlRxPacket(uint32 sadd,uint32 dadd,uint32 dsize)
{
g_dmaCTRLPKT.SADD = sadd; /* source address */
g_dmaCTRLPKT.DADD = dadd; /* destination address */
g_dmaCTRLPKT.CHCTRL = 0; /* channel control */
g_dmaCTRLPKT.FRCNT = 1; /* frame count */
g_dmaCTRLPKT.ELCNT = dsize; /* element count */
g_dmaCTRLPKT.ELDOFFSET = 0; /* element destination offset */
g_dmaCTRLPKT.ELSOFFSET = 0; /* element source offset */
g_dmaCTRLPKT.FRDOFFSET = 0; /* frame destination offset */
g_dmaCTRLPKT.FRSOFFSET = 0; /* frame source offset */
g_dmaCTRLPKT.PORTASGN = 4; /* port b */
g_dmaCTRLPKT.RDSIZE = ACCESS_64_BIT; /* read size */
g_dmaCTRLPKT.WRSIZE = ACCESS_64_BIT; /* write size */
g_dmaCTRLPKT.TTYPE = FRAME_TRANSFER ; /* transfer type */
g_dmaCTRLPKT.ADDMODERD = ADDR_FIXED; /* address mode read */
g_dmaCTRLPKT.ADDMODEWR = ADDR_FIXED; /* address mode write */
g_dmaCTRLPKT.AUTOINIT = AUTOINIT_ON; /* autoinit */
}
/* USER CODE END */
Ken Wang:
sam,
canREG1->CTL |= (uint32)(1<<18); // enable DMA for IF2 dmaReqAssign(DMA_CH1, 8); // DMA Configuration and Enable DMA dmaConfigCtrlRxPacket((uint32)(&TX_DATA1), (uint32)(&(canREG1->IF1DATx[0])), 1);
这几句话好像有点问题,你第一句设置的是enable IF2的DMA,后弦设置的硬件触发是request line是DCAN1 IF1。 是不是改下试试看。
谢谢
Sam:
回复 Ken Wang:
Ken,
不好意思,canREG1->CTL |= (uint32)(1<<18); 就使能DMA IF1, 注释出现的笔误;
dmaReqAssign(DMA_CH1, 8); // can1 的IF1 对应的request line 是8,
测试后不成功。。
Ken Wang:
回复 Sam:
sam,
我想了一下,我们用DMA去触发CAN总线的传输,这个其实不是太好操作。具体原因是:
1. 我们操作的DMA触发CAN的终端地址是IF1DATA[0],没有设置其他一些参数,包括你需要选择哪个messagebox。这个是个很重要的参数,因为你不设置对的messagebox,就不能通过相应的CANID把数据发出去,同时接收端也不一定能接到你的数据。
2.但我们用DMA去触发DMA的接收,这个操作确实可行的,因为它已经经过了CAN报文的解析,到达IF3里面的只是纯的数据了,这样就不会出错。
所以说用DMA去触发CAN总线的操作,不是太有效。当然也不是说完全不可以,有一个解决办法就是,你手动的设置数据发出的messagebox number。我刚试了一下,这个办法能行,但是效率太低。
具体的设置如下:
canREG2->IF1NO = canMESSAGE_BOX1;
所以还是建议你考虑一下,是不是不用DMA去触发CAN的数据发送,想想其他的办法解决一下。
有什么想法,我们再交流。
谢谢
Sam:
回复 Ken Wang:
Ken,
如果DMA发送数据部占优势的话, 那先就不考虑DMA发送数据了..
目前还有个问题关于DMA channel:
如果用DCAN1 DMA 接收数据 需要设置成dmaReqAssign(DMA_CH0, 4); 因为CAN1对应 request line 是 4 ..
如果用DCAN2 DMA 接收数据 需要设置成dmaReqAssign(DMA_CH1, 16); 因为CAN1对应 request line 是 16 ..
再这里我想问DMA_CH0这个通道的概念..DMA 有32个channel. 我大胆的猜想, 如果CAN1 将32个通道同时对应一个request line 4, 这样操作可行?
如果可行是不是传输数据更快?
Ken Wang:
回复 Sam:
Sam,
DMA channel只是为了方便设置DMA通道的优先级,因为我们芯片支持16个可独立配置的通道,如果一个系统里面用到了多个通道的话。他们在处理数据时,需要有相关的优先级仲裁,才能保证信息不被丢失。
默认情况下,channel的ID越小,优先级越大,当然这个也可以通过相关的寄存器设置。
如果你将32个通道连接到一个request line的话,这个数据传输可能会变慢。因为你32个通道都有数据发送,他们之间如果对应一个DMA request line的话,每一个CAN报文都需要等一个DMA传输结束后,才能去发送数据,然后在通过DMA去发送。还有一个问题就是,你需要在完成一次DMA操作后,再去配置新的DMA的寄存器,修改终端地址,这样效率会很低。
谢谢
Sam:
回复 Ken Wang:
Ken,
那就是一个CAN 对应一个channel, 每个channel对应一个request line, 每个源地址对应一个终端地址。这样是最常用的方式。
如果用多channel 来接收数据的话,是不是意义不大. 因为每个CAN 只有一个源地址IF3DATx? 再去不对切换channel和更改终端地址。。有点得不偿失?
效率也是没有提高。。反而再不断切换和修改Register 而浪费时间。。我理解的对吗?
Sam:
回复 Ken Wang:
Ken,
好的。明白了。谢谢!!