本帖最后由 月光疾風 于 2016-1-25 13:56 编辑
做了一个USB转CAN的工具,数据收发都OK了,但是动态配置CAN波特率碰到一点问题
现在抓换工具上电后任意配置1Mbps、500Kbps等等波特率均正常,可以通信,配置正确
但是如果我在第一次配置完成(比如配500Kbps),接着我又想改成用125Kbps的波特率
这时候125Kbps的配置下去后,单片机应该还是500Kbps的,125Kbps通信不上,
试了多种办法未果(貌似初次配置完成后MSCAN重新配置就不复位了),求高人指点一二~
附上初始化函数
//===========================================================================
//函数名称:CAN_Init
//功能概要:初始化MSCAN模块,采用24MHz总线时钟作为模块时钟
//参数说明:mode:工作模式选择:
// LOOP_MODE(0) - 回环模式
// NORMAL_MODE(1) - 普通模式
// baud:选择CAN常见波特率
// open_filter:接收过滤器开关
// 0x11 - 开启过滤器1,只接收标准标识符ID为acc_id的帧
// 0x12 - 开启过滤器1,只接收扩展标识符ID为acc_id的帧
// 0x21 - 开启过滤器2,只接收标准标识符ID为acc_id的帧
// 0x22 - 开启过滤器2,只接收扩展标识符ID为acc_id的帧
// 0x00 - 关闭过滤器,接收所有帧
// acc_id:接受ID,接收过滤器只接收标识符符合此ID的帧,过滤其他ID的帧
//函数返回:无
//===========================================================================
void CAN_Init(uint_8 mode,uint_16 baud,uint_8 open_filter,uint_32 acc_id)
{
uint_8 i;
MSCAN_MemMapPtr p = (MSCAN_MemMapPtr) MSCAN_BASE_PTR;
//MSCAN的引脚复用选择CAN_TX为PTC7,CAN_RX为PTC6
SIM_PINSEL1 &= (uint_32)~(uint_32)(SIM_PINSEL1_MSCANPS_MASK);
//MSCAN模块时钟门控制;SIM_SCGC的MSCAN位=1:使能总线给MSCAN时钟;
//SIM_SCGC的MSCAN位=0:禁止总线给MSCAN时钟
SIM_SCGC |=(uint_32)(SIM_SCGC_MSCAN_MASK);
//MSCAN12模块使能判断
if((p->CANCTL1 & MSCAN_CANCTL1_CANE_MASK) == 0)//为0 还未使能 不需要进入睡眠模式
{
//MSCAN12模块使能
p->CANCTL1 |= MSCAN_CANCTL1_CANE_MASK;
printf("First Init\r\n");
goto Normal;//跳过睡眠模式部分
}
//请求进入睡眠模式
//p->CANCTL0 |= MSCAN_CANCTL0_SLPRQ_MASK;
//等待应答进入睡眠模式
//while ((p->CANCTL1 & MSCAN_CANCTL1_SLPAK_MASK)== 0);
Normal:
//请求进入初始化模式
p->CANCTL0 |= MSCAN_CANCTL0_INITRQ_MASK;
//等待应答进入初始化模式
while ((p->CANCTL1 & MSCAN_CANCTL1_INITAK_MASK)== 0);
//配置时钟
p->CANCTL1 |= MSCAN_CANCTL1_CLKSRC_MASK; // 采用总线时钟(24MHz)作为模块时钟
//p->CANBTR0 |= MSCAN_CANBTR0_SJW(0);
p->CANBTR1 |= MSCAN_CANBTR1_SAMP_MASK; // 位时间采样次数为3
//p->CANBTR1 |= MSCAN_CANBTR1_SAMP_SHIFT; // 位时间采样次数为1
//选择波特率
switch(baud)
{
//1000bps
case 1000:
{
printf("\r\nCAN Baud=%dkbps\r\n",baud);
// MSCAN传输波特率 = 模块时钟 / [(1 + TSEG1 + TSEG2) * 分频因子]
// = 24000K/[(1+16+7)*1]=1000Kbps
p->CANBTR0 |= MSCAN_CANBTR0_BRP(0); // 模块时钟1分频
p->CANBTR0 |= MSCAN_CANBTR0_SJW(0); // SJW:0+1=1 Tq(1-4)
p->CANBTR1 |= MSCAN_CANBTR1_TSEG2(6); // TSEG2:6+1=7 Tq(1-8)
p->CANBTR1 |= MSCAN_CANBTR1_TSEG1(15); // TSEG1:15+1=16 Tq(1-16)
break;
}
//800Kbps
case 800:
{
printf("\r\nCAN Baud=%dkbps\r\n",baud);
// MSCAN传输波特率 = 模块时钟 / [(1 + TSEG1 + TSEG2) * 分频因子]
// = 24000K/[(1+7+7)*2]=800Kbps
p->CANBTR0 |= MSCAN_CANBTR0_BRP(1); // 模块时钟2分频
p->CANBTR0 |= MSCAN_CANBTR0_SJW(0); // SJW:0+1=1 Tq(1-4)
p->CANBTR1 |= MSCAN_CANBTR1_TSEG2(6); // TSEG2:6+1=7 Tq(1-8)
p->CANBTR1 |= MSCAN_CANBTR1_TSEG1(6); // TSEG1:6+1=7 Tq(1-16)
break;
}
//500Kbps
case 500:
{
printf("\r\nCAN Baud=%dkbps\r\n",baud);
//配置波特率
// MSCAN传输波特率 = 模块时钟 / [(1 + TSEG1 + TSEG2) * 分频因子]
// = 24000K/[(1+16+7)*2]=500Kbps
p->CANBTR0 |= MSCAN_CANBTR0_BRP(1); // 模块时钟2分频
p->CANBTR0 |= MSCAN_CANBTR0_SJW(0); // SJW:0+1=1 Tq
p->CANBTR1 |= MSCAN_CANBTR1_TSEG2(6); // TSEG2:6+1=7 Tq
p->CANBTR1 |= MSCAN_CANBTR1_TSEG1(15); // TSEG1:15+1=16 Tq
break;
}
//250Kbps
case 250:
{
printf("\r\nCAN Baud=%dkbps\r\n",baud);
// MSCAN传输波特率 = 模块时钟 / [(1 + TSEG1 + TSEG2) * 分频因子]
// = 24000K/[(1+16+7)*4]=250Kbps
p->CANBTR0 |= MSCAN_CANBTR0_BRP(3); // 模块时钟4分频
p->CANBTR0 |= MSCAN_CANBTR0_SJW(0); // SJW:0+1=1 Tq
p->CANBTR1 |= MSCAN_CANBTR1_TSEG2(6); // TSEG2:6+1=7 Tq
p->CANBTR1 |= MSCAN_CANBTR1_TSEG1(15); // TSEG1:15+1=16 Tq
break;
}
//125kbps
case 125:
{
printf("\r\nCAN Baud=%dkbps\r\n",baud);
// MSCAN传输波特率 = 模块时钟 / [(1 + TSEG1 + TSEG2) * 分频因子]
// = 24000K/[(1+16+7)*8]=125Kbps
p->CANBTR0 |= MSCAN_CANBTR0_BRP(7); // 模块时钟8分频
p->CANBTR0 |= MSCAN_CANBTR0_SJW(0); // SJW:0+1=1 Tq
p->CANBTR1 |= MSCAN_CANBTR1_TSEG2(6); // TSEG2:6+1=7 Tq
p->CANBTR1 |= MSCAN_CANBTR1_TSEG1(15); // TSEG1:15+1=16 Tq //125kbps
break;
}
//100kbps
case 100:
{
printf("\r\nCAN Baud=%dkbps\r\n",baud);
// MSCAN传输波特率 = 模块时钟 / [(1 + TSEG1 + TSEG2) * 分频因子]
// = 24000K/[(1+7+7)*16]=100Kbps
p->CANBTR0 |= MSCAN_CANBTR0_BRP(15); // 模块时钟16分频
p->CANBTR0 |= MSCAN_CANBTR0_SJW(0); // SJW:0+1=1 Tq(1-4)
p->CANBTR1 |= MSCAN_CANBTR1_TSEG2(6); // TSEG2:6+1=7 Tq(1-8)
p->CANBTR1 |= MSCAN_CANBTR1_TSEG1(6); // TSEG1:6+1=7 Tq(1-16)
break;
}
//50kbps
case 50:
{
printf("\r\nCAN Baud=%dkbps\r\n",baud);
// MSCAN传输波特率 = 模块时钟 / [(1 + TSEG1 + TSEG2) * 分频因子]
// = 24000K/[(1+7+7)*32]=50Kbps
p->CANBTR0 |= MSCAN_CANBTR0_BRP(15); // 模块时钟32分频
p->CANBTR0 |= MSCAN_CANBTR0_SJW(0); // SJW:0+1=1 Tq(1-4)
p->CANBTR1 |= MSCAN_CANBTR1_TSEG2(6); // TSEG2:6+1=7 Tq(1-8)
p->CANBTR1 |= MSCAN_CANBTR1_TSEG1(6); // TSEG1:6+1=7 Tq(1-16)
break;
}
//25kbps
case 25:
{
printf("\r\nCAN Baud=%dkbps\r\n",baud);
// MSCAN传输波特率 = 模块时钟 / [(1 + TSEG1 + TSEG2) * 分频因子]
// = 24000K/[(1+7+7)*64]=25Kbps
p->CANBTR0 |= MSCAN_CANBTR0_BRP(63); // 模块时钟64分频
p->CANBTR0 |= MSCAN_CANBTR0_SJW(0); // SJW:0+1=1 Tq(1-4)
p->CANBTR1 |= MSCAN_CANBTR1_TSEG2(6); // TSEG2:6+1=7 Tq(1-8)
p->CANBTR1 |= MSCAN_CANBTR1_TSEG1(6); // TSEG1:6+1=7 Tq(1-16)
break;
}
default:break;
}
//配置工作模式
if(LOOP_MODE == mode) p->CANCTL1 |= MSCAN_CANCTL1_LOOPB_MASK; // 开启回环模式
p->CANCTL1 &= ~MSCAN_CANCTL1_LISTEN_MASK; // 禁止侦听模式,即开启正常模式
//开启接收过滤器,只接收标示符为acc_id的帧
if(open_filter==0x11)//过滤器1过滤标准帧
{
// 使用2个32位接收过滤器
p->CANIDAC &= ~MSCAN_CANIDAC_IDAM_MASK;
// 第1个32位滤波器
// 设置接受寄存器的值
p->CANIDAR_BANK_1[0]=acc_id>>3;
p->CANIDAR_BANK_1[1]=acc_id<<5;
p->CANIDAR_BANK_1[2]=0xFF;
p->CANIDAR_BANK_1[3]=0xFF;
// 设置屏蔽寄存器的值
p->CANIDMR_BANK_1[0]=0x00;
p->CANIDMR_BANK_1[1]=0x1F;
p->CANIDMR_BANK_1[2]=0xFF;
p->CANIDMR_BANK_1[3]=0xFF;
}
else if(open_filter==0x12)//过滤器1过滤扩展帧
{
// 使用2个32位接收过滤器
p->CANIDAC &= ~MSCAN_CANIDAC_IDAM_MASK;
// 第1个32位滤波器
// 设置接受寄存器的值
p->CANIDAR_BANK_1[0]=acc_id>>21;
p->CANIDAR_BANK_1[1]=(acc_id & 0x001FE000)>>13;
p->CANIDAR_BANK_1[2]=(acc_id & 0x00001FE0)>>5;
p->CANIDAR_BANK_1[3]=(acc_id & 0x0000001F)<<3;
// 设置屏蔽寄存器的值
p->CANIDMR_BANK_1[0]=0x00;
p->CANIDMR_BANK_1[1]=0x00;
p->CANIDMR_BANK_1[2]=0x00;
p->CANIDMR_BANK_1[3]=0x1F;
}
else if(open_filter==0x21)//过滤器2过滤标准帧
{
// // 使用2个32位接收过滤器
// p->CANIDAC &= ~MSCAN_CANIDAC_IDAM_MASK;
// // 第1个32位滤波器
// // 设置接受寄存器的值
// p->CANIDAR_BANK_1[0]=acc_id>>3;
// p->CANIDAR_BANK_1[1]=acc_id<<5;
// p->CANIDAR_BANK_1[2]=0xFF;
// p->CANIDAR_BANK_1[3]=0xFF;
//
// // 设置屏蔽寄存器的值 1-忽略 0-匹配
// p->CANIDMR_BANK_1[0]=0x00;
// p->CANIDMR_BANK_1[1]=0x1F;
// p->CANIDMR_BANK_1[2]=0xFF;
// p->CANIDMR_BANK_1[3]=0xFF;
// // 第2个32位滤波器
// // 设置接受寄存器的值
// p->CANIDAR_BANK_2[0]=acc_id>>3;
// p->CANIDAR_BANK_2[1]=acc_id<<5;
// p->CANIDAR_BANK_2[2]=0xFF;
// p->CANIDAR_BANK_2[3]=0xFF;
//
// // 设置屏蔽寄存器的值
// p->CANIDMR_BANK_2[0]=0x00;
// p->CANIDMR_BANK_2[1]=0x1F;
// p->CANIDMR_BANK_2[2]=0xFF;
// p->CANIDMR_BANK_2[3]=0xFF;
}
else if(open_filter==0x00)//关闭过滤器
{
for (i = 0; i < 16; i++)
{
if(i>=0 && i <=3)
p->CANIDAR_BANK_1 = 0xFF;
else if(i>=4 && i <=7)
p->CANIDMR_BANK_1[i-4] = 0xFF;
else if(i>=8 && i <=11)
p->CANIDAR_BANK_2[i-8] = 0xFF;
else
p->CANIDMR_BANK_2[i-12]= 0xFF;
}
}
//退出初始化模式
p->CANCTL0 &= ~MSCAN_CANCTL0_INITRQ_MASK; //退出初始化模式,进入正常模式
//等待应答初始化模式
while ((p->CANCTL1 & MSCAN_CANCTL1_INITAK_MASK) == 1);
//请求退出睡眠模式
//p->CANCTL0 |= MSCAN_CANCTL0_SLPRQ_SHIFT;
//等待应答退出睡眠模式
//while ((p->CANCTL1 & MSCAN_CANCTL1_SLPAK_MASK)== 1);
//设置中断方式
p->CANTIER = 0x00; //禁止发送中断
p->CANRIER = 0x01; //开启接收满中断
//设置嵌套向量中断控制寄存器值,使能CAN接收中断
//NVIC_EnableIRQ(30);
NVIC_EnableIRQ(MSCAN_RX_IRQn);//IRQ号 30
//等待总线通信时钟同步
while ((p->CANCTL0 & MSCAN_CANCTL0_SYNCH_MASK) == 0);
}
|