【前言】
上篇完成了开箱报告,对华大的 HC32F460 开发板有了初步了解,从开发生态、官网资源、手册及软硬件资料等方面给大家做了介绍,非常感谢原厂和EEWorld 对我提到的意见做了详尽回复。此篇主要针对 HC32F460 该颗芯片的开发流程和一些试用过的通用外设做简单记录,分享给大家欢迎拍砖 。
【J-Flash下载】
刚装好官方pack包的情况下,有可能在J-Flash里面找不到对应的芯片设备,那该如何是好?这是由于SEGGER官方还未将华大所有的设备信息添加到驱动程序中,好在华大提供了补丁包,通过改写devices描述和添加下载算法的方式即可使用J-Link和J-Flash 对HC32F460进行调试烧录,具体的烧录方法与其它芯片操作流程一致,在此不做过多赘述。工具包以附件形式提供给大家,有需要的朋友可以拿去使用。主要需要按照下图描述拷贝补丁包:
【CAN控制器】
HC32F460的CAN控制器模块遵循 CAN 总线协议 2.0A 和 2.0B 协议并向上兼容 CAN-FD。具有 8 组独立的筛选器,有4 个 STB 以及 10 个 RB 可以理解为一个 4 级 FIFO 和一个 10 级 FIFO,接收和发送FIFO 完全由硬件控制。支持最高通信波特率 1Mbit/s,这么看起来 这个CAN模块功能挺齐全而且还能支持CAN-FD,先来看看官方例程中的CAN通信实验。
CAN例程包括了回环模式和普通模式的中断、轮训模式测试程序,很好奇难道CAN 不支持DMA方式?在手册中也没有明确找到DMA对应的所有通道到底是什么,可能没有看仔细吧。
先打开个中断方式的样例进行测试,CAN_RX和CAN_TX对应的引脚号是 PB06/PB07 :
程序中的初始化代码如下:
//<<System clk initial SysClkConfig(); //<<Enable can peripheral clock and buffer(ram) stcRamCfg.enRamOpMd = HighSpeedMd; stcRamCfg.enCan = DynamicCtl; PWC_RamCfg(&stcRamCfg); PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_CAN, Enable); //<<CAN GPIO config PORT_SetFunc(PortB, Pin06, Func_Can1_Rx, Disable); PORT_SetFunc(PortB, Pin07, Func_Can1_Tx, Disable); PORT_ResetBits(PortD, Pin15); PORT_OE(PortD, Pin15, Enable); //<<Can bit time config stcCanInitCfg.stcCanBt.PRESC = 1u-1u; stcCanInitCfg.stcCanBt.SEG_1 = 5u-2u; stcCanInitCfg.stcCanBt.SEG_2 = 3u-1u; stcCanInitCfg.stcCanBt.SJW = 3u-1u; stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 10u; stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 16u-1u; stcCanInitCfg.enCanRxBufAll = CanRxNormal; stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored; stcCanInitCfg.enCanSAck = CanSelfAckEnable; stcCanInitCfg.enCanSTBMode = CanSTBFifoMode; CAN_Init(&stcCanInitCfg); //<<Can filter config stcFilter.enAcfFormat = CanAllFrames; stcFilter.enFilterSel = CanFilterSel1; stcFilter.u32CODE = 0x00000000u; stcFilter.u32MASK = 0x1FFFFFFFu; CAN_FilterConfig(&stcFilter, Enable); //<<Can Irq Enable CAN_IrqCmd(CanRxIrqEn, Enable); stcIrqRegiConf.enIRQn = Int000_IRQn; stcIrqRegiConf.enIntSrc = INT_CAN_INT; stcIrqRegiConf.pfnCallback = &CAN_RxIrqCallBack; enIrqRegistration(&stcIrqRegiConf); NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT); NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn); NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
复制代码接着初始化CAN TX / RX 引脚,这里复用功能选择 disable 着实令人生疑 ,不应该是enable才对么? 而且没有明白 PD15置低电平起到啥作用 ;
然后再对CAN结构体模块进行初始化,波特率配置成了 1M ,这个作为例程来讲确实有点高,可能比较自信吧 。还对CAN的滤波器做了配置,屏蔽码code寄存器中应该也是 0代表相关 1代表无关的 ;
最后由于需要用中断方式接收处理数据,将CAN_RX 的中断服务开起来了,中断调用处理方式也是类似ST一样在一个总的中断服务处理函数文件中定义,并且进行回调,这里的回调函数为 CAN_RxIrqCallBack ,在 hc32f46x_interrupts.c 文件中的 IRQ000_Handler 中断服务函数中被系统调用,而且 采用的是给中断入口函数数组赋初始值的方式 将回调函数注册成功的,整个中断处理的这套逻辑还是做得不错的 。
void CAN_RxIrqCallBack(void){ if(true == CAN_IrqFlgGet(CanRxIrqFlg)) { CAN_IrqFlgClr(CanRxIrqFlg); CAN_IrqCmd(CanRxIrqEn, Disable); CAN_Receive(&stcRxFrame); u8RxFlag = true; } }
复制代码【中断控制器(INTC)】
通过手册可以知道,中断控制器(INTC)的功能有以下:
1. 选择中断事件请求作为中断输入到 NVIC,唤醒 WFI;
2. 选择中断事件请求作为事件输入,唤醒 WFE
3. 选择中断事件请求作为低功耗模式(休眠模式和停止模式)的唤醒条件;
4. 外部管脚 NMI 和 EIRQ 的中断控制功能;
5. 软件中断的中断/事件选择功能。
前面CAN例程也涉及到了中断控制器的使用,也有大致提及它的整个写法与ST 还是很不一样的。
第一步需要给 NVIC->IP赋值,这个是选择的IRQ通道号 ;
第二步需要设置中断优先级,也是对应的序号越小的优先级越高 ;
第三步本来直接使能通道即可,但是在华大ddl库例程中每次使能通道前会清除相应的标志位,可能是因为硬件不支持“未使能中断,中断标志位自动清除” 。
结合前面例程来看 有比较重要的几句代码:
typedef void (*func_ptr_t)(void);
func_ptr_t IrqHandler[IRQ_NUM_MAX] = {NULL};
en_result_t enIrqRegistration(const stc_irq_regi_conf_t *pstcIrqRegiConf){ // todo, assert ... stc_intc_sel_field_t *stcIntSel; en_result_t enRet = Ok; //DDL_ASSERT(NULL != pstcIrqRegiConf->pfnCallback); DDL_ASSERT(IS_NULL_POINT(pstcIrqRegiConf->pfnCallback)); /* IRQ032~127 whether out of range */ if (((((pstcIrqRegiConf->enIntSrc/32)*6 + 32) > pstcIrqRegiConf->enIRQn) || \ (((pstcIrqRegiConf->enIntSrc/32)*6 + 37) < pstcIrqRegiConf->enIRQn)) && \ (pstcIrqRegiConf->enIRQn >= 32)) { enRet = ErrorInvalidParameter; } else { stcIntSel = (stc_intc_sel_field_t *)((uint32_t)(&M4_INTC->SEL0) + \ (4u * pstcIrqRegiConf->enIRQn)); if (0x1FFu == stcIntSel->INTSEL) { stcIntSel->INTSEL = pstcIrqRegiConf->enIntSrc; IrqHandler[pstcIrqRegiConf->enIRQn] = pstcIrqRegiConf->pfnCallback; } else { enRet = ErrorUninitialized; } } return enRet; }
复制代码【写在最后】
限于篇幅,本次将评估 ADC TIMER UART等外设功能过程藏在自己心里,有机会再分享和学习,接下来点屏。
全部回复 5