Files
2026-07-03 18:08:25 +08:00

202 lines
4.4 KiB
C

#include "Includes.h"
typedef struct{
uint32_t id28_18:11;
uint32_t id17_00:18;
uint32_t ide:1;
uint32_t rtr:1;
uint32_t NA0:1;
uint32_t len;
uint8_t dat[8];
}CAN_INFO;
void can_pin_init(void)
{
gpio_mux_ctl(8,2);//tx
gpio_mux_ctl(9,2);//rx
}
/*
FPGA OSC_12M
tq=2*tclk(BRP+1) //CAN_BTR0->BRP
Tsyncseg=1*tq
Ttseg1=tq*(TSEG1+1) //CAN_BTR1->TSEG1
Ttseg2=tq*(TSEG2+1) //CAN_BTR1->TSEG2
can_baud=1/(Tsyncseg+Ttseg1+Ttseg2)
=1/(tq*(1+6+1+7+1))
=1/(tq*16)
=1/(16*2*tclk*(2+1))
=1/(16*6*tclk)
=1/(96*tclk)
=1/(96*(1/12M))=12M/96=12000000/96=125000bps
*/
void can_init(void)
{
__write_hw_reg32(((volatile unsigned *)(CPR_BASE+0x24)),0x00110014);//CPR_CTL_PCLK_GRCTL(pclk=mclk/2)
CPR_CAN_CLK_CTL->CAN_PCLK_EN=1;
CPR_CAN_CLK_CTL->CAN_MCLK_EN=1;
CPR_CAN_CLK_CTL->CAN_MCLK_DIV=0;
CAN_CDR->CDR3=0x07;
CAN_CDR->CDR4=0x0C;
// CAN_IER->TIE=1;
CAN_IER->RIE=1;
CAN_MOD->RM=1;
//config can baud
CAN_OCR->OCMODE=2;
CAN_BTR0->BRP=2;
CAN_BTR0->SJW=2;
CAN_BTR1->TSEG2=7;
CAN_BTR1->TSEG1=6;
//config can filter
CAN_MOD->AFM=1;//single filter
*CAN_ACR0=0x00;//id28-21
*CAN_ACR1=0x00;//id20-13
*CAN_ACR2=0x00;//id12-05
*CAN_ACR3=0x00;//id04-00 +rtr
*CAN_AMR0=0x00;//1 identify the corresponding bits as do not care
*CAN_AMR1=0x10;
*CAN_AMR2=0x00;
*CAN_AMR3=0x04;//*CAN_AMR3=0x04;
CAN_MOD->RM=0;
//config rev filter
}
uint8_t Buffer_Released,Transmission_Complete;
uint8_t can_send_mes(CAN_INFO *can_information)
{
uint8_t fifo_index;
//if(CAN_SR->TBS == 0) return 1;// CAN_SR->TBS ----volatile
while(CAN_SR->TBS == 0); //wait transmit buffer released. CAN_SR->TBS ----volatile
*CAN_FI = (can_information->len&(0xF))|((can_information->rtr)<<6)|((can_information->ide)<<7);//1:remote frame , 0:data frame
if(can_information->ide){//extended frame format
*CAN_ID1=(can_information->id28_18)>>3;
*CAN_ID2=(((can_information->id28_18)&0x07)<<5)|((can_information->id17_00)>>13);
*CAN_ID3=((can_information->id17_00)>>5)&0xFF;
*CAN_ID4=((can_information->id17_00)&0x1F)<<3;
fifo_index=2;
}else{ //standard frame format
*CAN_ID1=(can_information->id28_18)>>3;
*CAN_ID2=((can_information->id28_18)&0x07)<<5;
fifo_index=0;
}
if(can_information->rtr == 0)
{
for(uint8_t i=0;i<8;i++)
{
__write_hw_reg32(CAN_TX_BUFF(fifo_index++), can_information->dat[i]); //set transmission data
}
}
CAN_CMR->TR=0x01;
return 0;
}
uint8_t can_receive_msg(CAN_INFO *can_information)
{
uint8_t fifo_index;
if(CAN_SR->RBS==0) return 0;
can_information->ide = *CAN_FI&0x80 ? 1:0; /*0:standard_frame , 1:extended_frame*/
can_information->rtr = *CAN_FI&0x40 ? 1:0; /*0:data frame , 1:remote frame */
can_information->len = *CAN_FI&0xF;
if(can_information->len>8)
{
can_information->len=8;
}
can_information->id28_18=(*CAN_ID1<<3)|(*CAN_ID2>>5);
if(can_information->ide){//1:extended
can_information->id17_00=((*CAN_ID2&0x1F)<<13)|(*CAN_ID3<<5)|(*CAN_ID4>>3);
fifo_index=2;
}else{//1:standard
fifo_index=0;
}
if(can_information->rtr==0)
{
for(int i=0;i<can_information->len;i++)
{
__read_hw_reg32(CAN_RX_BUFF(fifo_index++), can_information->dat[i]);
}
}
CAN_CMR->RRB=1; /* Release the FIFO */
return can_information->len;
}
void tx_msg(void)
{
static CAN_INFO can_tmsg={
.rtr=0,//1:remote frame , 0:data frame
.ide=1,//1:extended frame format , 0:standard frame format
.len=8,
.id28_18=0x12,
.id17_00=0x73,
.dat[0]=0x01,
.dat[1]=0x02,
.dat[2]=0x03,
.dat[3]=0x04,
.dat[4]=0x05,
.dat[5]=0x06,
.dat[6]=0x07,
.dat[7]=0x08,
};
#if 1 //tx
can_tmsg.dat[0]++;
if(can_tmsg.rtr)//1: remote frame(remote frame has no data part)
{
if(can_tmsg.len>=8)
{
can_tmsg.len=1;//request length
}else
{
can_tmsg.len++;//request length
}
}
can_send_mes(&can_tmsg);
#endif
}
void rx_msg(void)
{
CAN_INFO can_rmsg;
if(can_receive_msg(&can_rmsg))
{
printf("id28_18=%#x ,id17_00=%#x ,rtr=%#x ,ide=%#x ,len=%#x \n",can_rmsg.id28_18,can_rmsg.id17_00,can_rmsg.rtr,can_rmsg.ide,can_rmsg.len);
if(can_rmsg.rtr==0)
{
printf("dat:");
for(int i=0;i<can_rmsg.len;i++) printf("%#x ",can_rmsg.dat[i]);
printf("\n");
}
}
}
void CAN_Handler(void)
{
rx_msg();
}
void test_can(void)
{
can_pin_init();
can_init();
NVIC_EnableIRQ(CAN_IRQn);
while(1)
{
tx_msg();
}
}