学习一下官方提供的ECAN程序的例程:
本程序完成如下的功能:
-
配置时钟,初始化ECAN和DMA和液晶
-
发送一个ECAN的帧
-
在主循环中,判断是否收到帧,收到则进行帧的处理。
程序流程
/*****************************************************************************************************
Configuration bits:
_FOSCSEL: Start up with the FRC oscillator
_FOSC: Use Primary oscillator XT w/ PLL, Two-speed Oscillator Startup enabled
_FWDT: Watch dog timer is off
_FPOR: Power-on Reset Value disabled, Alternate I2C pins mapped to SDA1/SCL1
_FICD: JTAG is disabled, communicate on PGC3/EMUC3 and PGD3/EMUD3 for explorer 16 development board
*****************************************************************************************************/
_FOSCSEL(FNOSC_FRC)
_FOSC(FCKSM_CSECMD & POSCMD_XT)
_FWDT(FWDTEN_OFF)
_FPOR(FPWRT_PWR1)
_FICD(JTAGEN_OFF & ICS_PGD1)
MPLABX生成的配置字程序,太长了,不是一般的难看。
-
时钟配置
-
申明两个全局的结构体,一个是CAN接收消息,一个是CAN发送消息,结构体如下;
//消息结构体
typedef struct{
unsigned char buffer_status;//状态
unsigned char message_type;//远程帧还是数据
unsigned char frame_type;//标准模式还是扩展模式
unsigned char buffer;//用来发送和接收的缓存
unsigned long id;//ID号,两种模式
unsigned char data[8];//数据域
unsigned char data_length;//数据长度
}mID;
/* Define ECAN Message Buffers */
ECAN1MSGBUF ecan1msgBuf __attribute__((space(dma),aligned(ECAN1_MSG_BUF_LENGTH*16)));
char mytext[]="Microchip Inc. ";
char mytext1[]="TBXXX Demo";
-
主函数
-
配置时钟
-
初始化ECAN,初始化DMAECAN
-
Welcome消息
-
使能ECAN1中断,使能发送和接收中断
-
填充结构体,生成一个帧格式
-
将一个合成的帧发送出去
-
while循环中做如下的操作
-
如果BUFFER的状态中,BUF为满,则将消息读到RAM中。
-
消息显示在液晶上
-
清消息满的状态
-
否则做其他的操作
初始化ECAN:
void initECAN (void)
{
unsigned long temp;
unsigned int tempint;
C1CTRL1bits.REQOP=4; //进入配置模式,或者用库函数中设置操作模式的函数来编写
while(C1CTRL1bits.OPMODE != 4); //等待确实进入了配置模式
//配置C1CFG1和C1CFG2的值,或者用初始化ECAN的函数来写。
Bit Time = (Sync Segment + Propagation Delay + Phase Segment 1 + Phase Segment 2)=20*TQ
Phase Segment 1 = 8TQ
Phase Segment 2 = 6Tq
Propagation Delay = 5Tq
Sync Segment = 1TQ
CiCFG1 =(FCAN /(2 譔譌BAUD))?1
BIT RATE OF 1Mbps
*/
C1CFG1bits.BRP = BRP_VAL;
/* Synchronization Jump Width set to 4 TQ */
C1CFG1bits.SJW = 0x3;
/* Phase Segment 1 time is 8 TQ */
C1CFG2bits.SEG1PH=0x7;
/* Phase Segment 2 time is set to be programmable */
C1CFG2bits.SEG2PHTS = 0x1;
/* Phase Segment 2 time is 6 TQ */
C1CFG2bits.SEG2PH = 0x5;
/* Propagation Segment time is 5 TQ */
C1CFG2bits.PRSEG = 0x4;
/* Bus line is sampled three times at the sample point */
C1CFG2bits.SAM = 0x1;
//设置BUFFER的尺寸。
C1FCTRLbits.DMABS=0b000;
/* Filter configuration */
//使用Filter还是BUFFER,配置完以后,清空,直接指向缓存。
C1CTRL1bits.WIN=0b1;
C1FMSKSEL1bits.F0MSK=0;//选择F1为M0模式
C1RXM0SID=CAN_FILTERMASK2REG_SID(0x7FF);//每位都需要比较!!
C1RXF0SID=CAN_FILTERMASK2REG_SID(0x123);//ID为0X123
C1RXM0SID=CAN_SETMIDE(C1RXM0SID);//MIDE设置为1时候,再看EXIDE是0还是1来决定标准ID模式还是EXID模式。
C1RXF0SID=CAN_FILTERSTD(C1RXF0SID);//将EXIDE设置为0,只接收标准模式
C1BUFPNT1bits.F0BP=0b0001;//缓冲指针指向1,
C1FEN1bits.FLTEN0=1;//使能FILTER0
//上面的整体设置思路是,F0选择M0,然后设置M0是每位都要匹配,然后设置匹配的ID,然手设置成ID模式,选择标准模式,然后设置指向的缓存,再使能配置好了的F0,
C1FMSKSEL1bits.F1MSK=0b01;//选择F1为M2模式
C1RXM1EID=CAN_FILTERMASK2REG_EID0(0xFFFF);//采用扩展模式,这位是全部需要比较
C1RXM1SID=CAN_FILTERMASK2REG_EID1(0x1FFF);//采用扩展模式,标准模式的11要比较,再加上最后两位也需要比较
C1RXF1EID=CAN_FILTERMASK2REG_EID0(0x5678);//29位ID,写入寄存器
C1RXF1SID=CAN_FILTERMASK2REG_EID1(0x1234);//29位ID,写入寄存器
C1RXM1SID=CAN_SETMIDE(C1RXM1SID);//查扩展ID是否匹配
C1RXF1SID=CAN_FILTERXTD(C1RXF1SID);
C1BUFPNT1bits.F1BP=0b0010;//指向缓冲为2
C1FEN1bits.FLTEN1=1;//使能该F1
C1FMSKSEL1bits.F2MSK=0b01;//F2继续使用F1的M1作为规则
C1RXF2EID=CAN_FILTERMASK2REG_EID0(0x5679);//M1已经定义好,不需要再重新定义
C1RXF2SID=CAN_FILTERMASK2REG_EID1(0x1234);//继续写入29位ID到寄存器中
C1RXF2SID=CAN_FILTERXTD(C1RXF2SID);//这里,M里面的那位不再需要定义,直接需要查拓展ID,前面已经定义好
C1BUFPNT1bits.F2BP=0b0011;//指向缓冲
C1FEN1bits.FLTEN2=1;//使能F2
//关掉设置窗口,直接指向缓存
C1CTRL1bits.WIN=0;
//模式设置回正常模式,等待确实回到正常模式
C1CTRL1bits.REQOP=0;
while(C1CTRL1bits.OPMODE != 0);
//接收缓存满,溢出都设置为0
C1RXFUL1=C1RXFUL2=C1RXOVF1=C1RXOVF2=0x0000;
//设置四个缓存的方向,是发送还是接收,下面的设置,缓存0为发送,123为接收
C1TR01CONbits.TXEN0=1;
C1TR01CONbits.TXEN1=0;
C1TR23CONbits.TXEN2=0;
C1TR23CONbits.TXEN3=0;
//设置缓存0的优先级为最高。
C1TR01CONbits.TX0PRI=0b11;
//再请一次满标志,然后设置满中断标志为0
C1RXFUL1=0;
C1INTFbits.RBIF=0;
}
初始化DMA
void initDMAECAN(void)
{
//DMA的通道给DMA作为发送,先情况冲突标志
DMACS0=0;
DMA0CON=0x2020; //第一个位,方向,从DPSRAM中读,写入外设,第二位,外设直接地址模式
DMA0PAD=0x0442; //既然设置成外设直接地址,当然要提供一个外设的地址,ECAN1发送的地址为0X0442
DMA0CNT=7; //要发送的数量
DMA0REQ=0x0046; //这个是请求号,ECAN1的请求号是0X0046
DMA0STA=__builtin_dmaoffset(&ecan1msgBuf); //发送的数据指向指针
DMA0CONbits.CHEN=1; //使能通道1
//下面设置的是接收,和发送类似。
DMACS0=0;
DMA2PAD=0x0440;
DMA2CNT=7;
DMA2REQ=0x0022;
DMA2STA=__builtin_dmaoffset(&ecan1msgBuf);
DMA2CONbits.CHEN=1;
}
液晶显示初始化:略
使能中断
//使能中断,使能ECAN中断,发送中断和接收中断,ECAN一共还有7中中断,包括无效消息中断,总线唤醒,错误中断,FIFO满中断,接收满中断和发送中断,接收中断。
IEC2bits.C1IE=1;
C1INTEbits.TBIE=1;
C1INTEbits.RBIE=1;
合成需要发送的数据帧:
//要发送的帧结构体定义
canTxMessage.message_type=CAN_MSG_DATA; //数据帧
//canTxMessage.message_type=CAN_MSG_RTR;
canTxMessage.frame_type=CAN_FRAME_EXT; //扩展帧
//canTxMessage.frame_type=CAN_FRAME_STD;
canTxMessage.buffer=0; //写入的buffer0
canTxMessage.id=0x123; //ID号
canTxMessage.data[0]=0x55; //填入发送的8位数据
canTxMessage.data[1]=0x55;
canTxMessage.data[2]=0x55;
canTxMessage.data[3]=0x55;
canTxMessage.data[4]=0x55;
canTxMessage.data[5]=0x55;
canTxMessage.data[6]=0x55;
canTxMessage.data[7]=0x55;
canTxMessage.data_length=8;//数据长度为8
/***************************************************/
2013年是移动互联网的元年,移动互联网大大提高了我们工作和生活的效率。
罗辑思维用互联网思维网络了大量的会员,最近又在召集用互联网思维来吃霸王餐。
我们不需要那么牛气哄哄,互联网思维既然能够解决这样的大事,那小事当然更没问题。
利用互联网思维做一个晨型人,也应该不是一件难事吧。
操作模式如下:申请一个微信公众号,分享作为晨型人一天的收获。
以及在遇到困难的时候,如果克服自己,解决问题。
如果有兴趣,扫一扫下面的公众号 吧,让我们一起轻松的做一个快乐的晨型人。
/***************************************************/
文章评论(0条评论)
登录后参与讨论