在使用串口 DMA 接收的时候,发现驱动库提供的接口并不能满足实际需要。具体表现为,串口的 DMA 是工作在循环模式下的,这就要求在必要的时候可以获取 DMA 接收的数据长度,不过驱动库貌似没有对应的接口!
DMA 驱动中只有设置接口,没有读取接口! 。无奈自己增加了几个接口! GPIO
华大应该称为 PORT 时钟
貌似,华大 MCU 并不能像 ST MCU 似得,开启或者关闭某个 GPIO 的时钟。所以在配置 IO 时,无需要处理时钟的问题。 特殊配置
某些 IO 在上电时默认是用作其他功能的。例如:
PA13,PA14,PA15,PB3,PB4 端口复位后初始状态为 JTAG/SWD 功能有效。
PC14,PC15 端口复位后初始状态为数字功能禁止状态
PA11,PA12 与 USBFS_DM,USBFS_DP 引脚复用,内藏约 400KΩ 的下拉电阻,且一直有效。
端口 PB11 与 MD 复用,为输入专用端口,无输出功能
这一点貌似和 STM32F1x 的使用情况是一致的。因此,如果需要将上面的 IO 作为普通 IO 使用,则必须进行特殊配置,然后才能进行正常的 IO 配置!
PA13,PA14,PA15,PB3,PB4 在配置 FSEL 选择功能时需要先将寄存器 PSPCR 相应位写 0 无效JTAG/SWD 功能。对应的库函数接口 en_result_t PORT_DebugPortSetting(uint8_t u8DebugPort, en_functional_state_t enFunc);
PC14,PC15 在选择数字功能时需要先将相应寄存器 PCRxy 的 DDIS 位写 0 有效数字功能。这个在进行 IO 配置时,在en_result_t PORT_Init(en_port_t enPort, uint16_t u16Pin, const stc_port_init_t *pstcPortInit); 中就有对应的处理。
当系统运行在高速时钟下,由于 I/O 输入存在延迟,单周期可能无法正确读取输入状态值。此时需要设置寄存器 PCCR.RDWT,插入若干等待周期。 外设引脚映射
具体见用户手册的 2.2 引脚功能表。在我的项目中,出现了 SPI_CLK 引脚无法映射的问题。 程序下载异常
在使用中发现,在下载程序之后并不能正常启动。我的项目结构是 IAP(在线升级) + APP,每次下载 APP 之后,IAP 就会被清除。一开始没有具体分析错误的原因的情况下,想当然的通过如下解决方法来处理。
但是,如上图修改之后,在实际下载的时候,Keil 会提示如下的警告,不过貌似没啥影响
虽然调试没啥影响,但是在生成 .bin 文件时却会出现错误! 但实际该方法并没有解决根本。通过详细分析,最后发现该问题是由于看门狗的配置导致的。具体:由于 APP 中包含了 看门狗的配置,看门狗的配置其实是 FLASH 中的固定一块空间。我们的 APP 偏移之后,自然没有看门狗部分的操作算法! 最终解决方法: 我们不需要上面的更改,只需要将看门狗的配置放到 IAP 中即可! IAP 肯定是从起始地址开始,自然不会有问题! 外设反初始化
我的项目结构是 IAP(在线升级) + APP,外设在 IAP 中工作正常,但是在 APP 中工作不正常。这主要是由于:外设在 IAP 中已经初始化,然而在调整到 APP 之后,这部分外设由于已经被初始化,导致不会再次被初始化。这一点其实对于 ST 的 MCU 同样适用。因此,需要我们来特殊处理! 例如 hc32f46x_interrupts.c/h 中配置的中断,如果在 IAP 中已经被设置,跳转到 APP 后,就无法再正常配置了(全局变量中会检查是否被配置过)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->pfnCallback;
}
else
{
enRet = ErrorUninitialized;
}
}
return enRet;
}
具体方法就是使用 enIrqResign 函数进行重新标记! 内容很详细,支持一下
页:
1
[2]