[学习笔记] 寄存器学习之can

[复制链接]
2754|12
手机看帖
扫描二维码
随时随地手机跟帖
JasonLee27|  楼主 | 2020-7-27 14:11 | 显示全部楼层 |阅读模式
硬件环境:AC7801x 通用开发板  ATC-LINK
软件环境:keil 5.23


上一章节完成了clock,让芯片运行在48M PLL下,这次我们主要完成下面三个工作:
1,让延时更精确,将采用systick进行延时,实现延时功能
2,增加休眠唤醒,让芯片可以进入休眠以及唤醒
3,增加CAN模块的收发功能

一,使用systick进行延时,可直接参照驱动中的实现。
/*!
* [url=home.php?mod=space&uid=247401]@brief[/url] delay until the syctick count tick to 0
*
* @param[in] tick : systick count value
* [url=home.php?mod=space&uid=266161]@return[/url] none
*/
static void SysTickDelay(uint32_t tick)
{
    __IO uint32_t tickFlag = 0;

    SysTick->LOAD = tick - 1;
    SysTick->VAL = 0x00;
    SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
    do
    {
        tickFlag = SysTick->CTRL;

    } while(!(tickFlag & SysTick_CTRL_COUNTFLAG_Msk));

    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    SysTick->VAL = 0X00;
}

/*!
* [url=home.php?mod=space&uid=247401]@brief[/url] Repeatlly delay the ticks for the given times
*
* @param[in] param : times, the times of delay the tick
* @param[in] param : tick, each tick to delay
* [url=home.php?mod=space&uid=266161]@return[/url] none
*/
static void SysTickRepeatDelay(uint32_t times, uint32_t tick)
{
    uint32_t i = 0;

    for (i = 0; i < times; i++)
    {
        SysTickDelay(tick);
    }
}

/*!
* @brief delay us
*
* @param[in] param : us, us for delay
* @return none
*/
void udelay(uint32_t us)
{
    uint32_t tick = us * s_facus;

    SysTickRepeatDelay(tick / MAX_SYSTICK_COUNT, MAX_SYSTICK_COUNT);

    SysTickDelay(tick % MAX_SYSTICK_COUNT);
}

/*!
* @brief delay ms
*
* @param[in] param : ms, us for delay
* @return none
*/
void mdelay(uint32_t ms)
{
    uint32_t tick = ms * s_facms;

    SysTickRepeatDelay(tick / MAX_SYSTICK_COUNT, MAX_SYSTICK_COUNT);

    SysTickDelay(tick % MAX_SYSTICK_COUNT);
}
二,芯片进入stop模式
此处设置stop1,同时使能spm,关闭LVD是为了让功耗更低,第三行似乎是内部的一些操作,也保留了下来。
最后就是arm内核的休眠操作了。

void sysStop(void)
{
    MODIFY_REG32(SPM->PWR_MGR_CFG0, SPM_PWR_MGR_CFG0_SLEEP_MODE_Msk, SPM_PWR_MGR_CFG0_SLEEP_MODE_Pos, 1);   ///<set stop 1 mode
    SET_BIT32(SPM->PWR_MGR_CFG0, SPM_PWR_MGR_CFG0_PWR_EN_Msk);  ///<enable spm
    MODIFY_MEM32(REG_PORLPVD_CFG0_ADDR, LOW_POWER_CFG_MASK, LOW_POWER_CFG_START_BIT, LOW_POWER_CFG_VALUE);
    CLEAR_BIT32(SPM->PWR_MGR_CFG0, SPM_PWR_MGR_CFG0_EN_DPWRLVD_Msk);    ///<disable LVD
   
    /* Set the SLEEPDEEP bit to enable deep sleep mode (STOP) */
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
   
    // If using KEIL's uVision, use the CMSIS intrinsic
    __wfi();
}
当然,在进入休眠前,少不了要使能一些唤醒,否则就起不来了,所以在外层再封装一个函数,此处使能了GPIO以及CAN唤醒
void Mcu_GotoLowPower(void)
{
    SPM->EN_PERIPH_WAKEUP |= SPM_EN_PERIPH_WAKEUP_CAN0_Msk | SPM_EN_PERIPH_WAKEUP_GPIO_Msk; ///<enable wakeup
    sysStop();
   
}
三,can实现,对于can实现的具体就不细说了,对于一般的使用来说,can确实没有太多东西需要初始化的。在can.h文件中实现了如下接口。
typedef struct _can_msg
{
    uint32_t    ID;
    uint32_t     DLC:4;                               /*!< Data length code */
    uint32_t     FDF:1;                               /*!< FD format indicator */
    uint32_t     IDE:1;                               /*!< Identifier extension */
    uint32_t     reserved:26;
    uint8_t     DATA[64];                             /*!< Data must 4bytes align*/
}CanMsgType;
   
extern void Can_Init(void);
   
extern void Can_DeInit(void);

extern int Can_Transmit(CanMsgType *canMsg);

extern int Can_Receive(CanMsgType *canMsg);
整体工程实现过程中遇到如下问题:
1,can模块DATA域必须4字节对齐
在cortex-m0+中是不支持非对齐访问的,而can模块的RBUF和TBUF又都是按照4字节访问,所以在访问时我们需要将我们定义的结构体中的DATA成员转为uint32,如果DATA未四字节对齐,将会导致非对齐访问错误而进入hardfault
CANx->TBUF.DATA[i>>2] = *(uint32_t *)(&canMsg->DATA[i]);
所以在定义can结构体时,需要在前面填充,以确保声明的DATA[64]起始地址是4字节对齐的

2,can模块初始化时,部分寄存器在RESET=1时初始化,部分在RESET=0时初始化
这涉及到CAN模块的软件复位功能,在参考手册ATC_AC7801x_ReferenceManual_CH.pdf 的7.3.11节有说明。这里主要是设置CAN波特率的寄存器,以及CANFD选择寄存器需要在RESET=1下写入,RESET=0时就锁定了。
void Can_Init(void)
{
    CKGEN->CTRL |= CKGEN_CTRL_CAN0_CLK_SEL_Msk;
    CKGEN->PERI_CLK_EN_0 |= CKGEN_PERI_CLK_EN_0_CAN0_EN_Msk;    ///<CAN clock en
    CKGEN->PERI_SFT_RST0 |= CKGEN_PERI_SFT_RST0_SRST_CAN0_Msk;
   
    CANx->CTRL0 |= CAN_CTRL0_RESET_Msk; ///<CAN set reset some register must write while RESET=1 and lock while RESET=0
   
    CANx->CTRL0 |= CAN_CTRL0_FDISO_Msk; ///<CANFD
    /*
        tSeg1 = (S_SEG_1 + 2); tSeg2 = (S_SEG_2 + 1).
        BandRate         = (48M / (S_PRESC + 1) / ((S_SEG_1 + 2) + (S_SEG_2 + 1))) = 500K
        SamplePoint = (tSeg1 / (tSeg1 + tSeg2)) = 81.25%.
    */
    CANx->SBITRATE = (5 << CAN_BITRATE_PRESC_Pos) + (2 << CAN_BITRATE_SJW_Pos) + (2 << CAN_BITRATE_SEG_2_Pos) + 11; ///<Low speed
   
    ///<1M  81.25%
    CANx->FBITRATE = (2 << CAN_BITRATE_PRESC_Pos) + (2 << CAN_BITRATE_SJW_Pos) + (2 << CAN_BITRATE_SEG_2_Pos) + 11; ///<High speed
   
   
    CANx->CTRL0 &= ~CAN_CTRL0_RESET_Msk; ///<CAN reset
   
   
    CANx->CTRL1 &= ~0xFE;   ///<clear all interrupt enable
   
    CANx->CTRL1 |= (CAN_CTRL1_EIE_Msk | CAN_CTRL1_RIE_Msk | CAN_CTRL1_TSIE_Msk | CAN_CTRL1_TPIE_Msk);   ///<enable send receive and error interrupt
   
    CANx->CTRL1 |= (15 << CAN_CTRL1_EWL_Pos);   ///<EIF limit value set 128 ((EWL+1)*8)
   
    NVIC_EnableIRQ(CAN0_IRQn);
}
3,对于can模块,只使用STB发送,接收未设软件buff,因为STB本身已经有一个3深度的发送缓冲区,同时接收缓冲区的深度为7,加快一下芯片接收处理的速度,完全可以做到不需要软件buff,再不济可以使用硬件过滤,去除不需要接收的ID,更能减少接收的报文,避免溢出。

话说,代码好像挺多了。
Program Size: Code=2024 RO-data=240 RW-data=8 ZI-data=1264  

can.rar (371.9 KB)

使用特权

评论回复
zeshoufx| | 2020-7-28 14:33 | 显示全部楼层
谢谢分享【 寄存器学习之can】

使用特权

评论回复
guanxiangli| | 2022-1-12 11:30 | 显示全部楼层
我也在搞CAN唤醒,请问楼主配置完这些后只要发送数据触发中断就会唤醒MCU吗

使用特权

评论回复
JasonLee27|  楼主 | 2022-1-12 18:04 | 显示全部楼层
guanxiangli 发表于 2022-1-12 11:30
我也在搞CAN唤醒,请问楼主配置完这些后只要发送数据触发中断就会唤醒MCU吗 ...

CAN唤醒功能实际上是由SPM模块实现,CAN模块不开都没关系,关键是CAN RX引脚要配置为CAN RX功能,然后SPM模块要使能CAN唤醒。休眠后RX脚为低电平唤醒。拉低CAN RX脚就可以唤醒了

使用特权

评论回复
tail066| | 2022-2-14 10:32 | 显示全部楼层
感谢分享
后面会不会出连载,哈哈哈哈~

使用特权

评论回复
内政奇才| | 2022-2-14 11:37 | 显示全部楼层
学习了

使用特权

评论回复
内政奇才| | 2022-2-14 11:38 | 显示全部楼层
学习了

使用特权

评论回复
维维biu| | 2022-4-25 10:26 | 显示全部楼层
回环能发送,正常模式发送不出去什么情况

使用特权

评论回复
cyclefly| | 2022-5-17 21:09 | 显示全部楼层
什么是回环

使用特权

评论回复
两只袜子| | 2022-5-18 09:50 | 显示全部楼层
能把代码框换一种颜色吗?看着很吃力

使用特权

评论回复
sadicy| | 2022-6-5 09:44 | 显示全部楼层
can和lin在车上基本就用这两种吧

使用特权

评论回复
koala889| | 2022-6-13 21:19 | 显示全部楼层
好贴需要反复看

使用特权

评论回复
andygirl| | 2022-6-14 21:18 | 显示全部楼层
真不错啊~

使用特权

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

本版积分规则