打印
[汽车MCU – KEA]

调试KEA128的MSCAN碰到一个问题

[复制链接]
3759|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
月光疾風|  楼主 | 2016-1-25 13:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 月光疾風 于 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);
}

相关帖子

沙发
月光疾風|  楼主 | 2016-1-25 18:05 | 只看该作者
没人看么

使用特权

评论回复
板凳
Thethree| | 2016-1-25 20:22 | 只看该作者

有没有类似stm32那种库函数版本的啊

使用特权

评论回复
地板
月光疾風|  楼主 | 2016-1-25 22:05 | 只看该作者
Thethree 发表于 2016-1-25 20:22
有没有类似stm32那种库函数版本的啊

可以参考这个帖子https://bbs.21ic.com/forum.php?mo ... peid%26typeid%3D378

使用特权

评论回复
5
fortunely| | 2016-1-26 19:44 | 只看该作者
重新配置时,可以先清除所有寄存器值为reset后的值;双方重新配置波特率总需要一个约定时间吧,你需要一个通讯的过程,通讯确认完成后再定时转入重新配置can

使用特权

评论回复
6
月光疾風|  楼主 | 2016-1-26 22:45 | 只看该作者
fortunely 发表于 2016-1-26 19:44
重新配置时,可以先清除所有寄存器值为reset后的值;双方重新配置波特率总需要一个约定时间吧,你需要一个 ...

通信协议是有的,明天试下这个办法

使用特权

评论回复
7
月光疾風|  楼主 | 2016-1-28 12:56 | 只看该作者
问题解决了,解决办法,通过软件复位实现参数的重新配置,这样可以保证MSCAN模块每次重新配置参数的时候都上电复位效果一样,通信协议中加入复位指令,调用NVIC_SystemReset();//软件复位这个函数即可

使用特权

评论回复
8
zuoke503| | 2017-3-15 09:17 | 只看该作者
楼主,你的工程是CW编译的吗?能不能把工程文件分享一下。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

32

帖子

1

粉丝