关于新唐NUC029LAN库函数操作无法打开定时器2和定时器3的问题(库函数中的bug)

结论:

问题:使用NUC029LAN库函数中的设备时钟使能函数时,无法正常打开定时器TMR2和TMR3。
原因:clk.h中,定时器2模块(TMR2_MODULE)和定时器3模块(TMR2_MODULE)的值有问题。


解决办法:
库函数的clk.h中,TMR2_MODULE 和 TMR3_MODULE的值如下更改:在这里插入图片描述
在这里插入图片描述


项目场景:

使用NUC029LAN库函数中的设备时钟使能函数,使能定时器1~4的模块时钟。

问题描述:

在使用设备时钟使能库函数(如下)时,定时器TMR2、TMR3无法正常工作。

    CLK_EnableModuleClock(TMR0_MODULE);		// 使能TMR0模块时钟		
    CLK_EnableModuleClock(TMR1_MODULE);		// 使能TMR1模块时钟		
    CLK_EnableModuleClock(TMR2_MODULE);		// 使能TMR2模块时钟		
    CLK_EnableModuleClock(TMR3_MODULE);		// 使能TMR3模块时钟		


原因分析:

设备时钟使能库函数CLK_EnableModuleClock(uint32_t u32ModuleIdx)源码如下:

/**
  * @brief  This function enable module clock		使能APB设备时钟
  * @param  u32ModuleIdx is module index. Including :
  *   - \ref WDT_MODULE			 		     看门狗	时钟使能控制 (写保护) 
  *   - \ref TMR0_MODULE		 			Timer0	时钟使能控制 
  *   - \ref TMR1_MODULE		 			Timer1	时钟使能控制 
  *   - \ref TMR2_MODULE		 			Timer2	时钟使能控制 
  *   - \ref TMR3_MODULE		 			Timer3	时钟使能控制 
  *   - \ref FDIV_MODULE				 分频器输出	时钟使能控制
  *   - \ref I2C0_MODULE			          I2C0	时钟使能控制
  *   - \ref I2C1_MODULE					  I2C1	时钟使能控制
  *   - \ref SPI0_MODULE					  SPI0	时钟使能控制
  *   - \ref SPI1_MODULE					  SPI1	时钟使能控制
  *   - \ref UART0_MODULE					 UART0	时钟使能控制
  *   - \ref UART1_MODULE					 UART1	时钟使能控制
  *   - \ref PWM01_MODULE					PWM_01	时钟使能控制
  *   - \ref PWM23_MODULE					PWM_23	时钟使能控制
  *   - \ref PWM45_MODULE					PWM_45	时钟使能控制
  *   - \ref PWM67_MODULE		 			PWM_67	时钟使能控制
  *   - \ref ADC_MODULE			 			   ADC	时钟使能控制
  *   - \ref ACMP01_MODULE			  模拟比较器0/1	时钟使能控制
  *   - \ref ACMP23_MODULE		 	  模拟比较器2/3	时钟使能控制
  * @return None		无返回值
  */
//	使能APB设备时钟控制(选择模块)
void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
{
	// 下列等式等价为 APBCLK = APBCLK | (1<<(CLK_APBCLK_xxxx_EN_Pos))		
	// (APBCLK + (MODULE_APBCLK(u32ModuleIdx) * 4))	——	APBCLK寄存器加上库函数原始定义的APBCLK的复位值(0x000_000X)
    *(volatile uint32_t *)((uint32_t)&CLK->APBCLK + (MODULE_APBCLK(u32ModuleIdx) * 4))  |= 1 << MODULE_IP_EN_Pos(u32ModuleIdx);
}
对比后发现,使用寄存器操作(如下)时,定时器TMR2、TMR3可以正常工作。

    /* Enable peripheral clock */
    // 使能UART0、TMR0、TMR1、TMR2、TMR3模块时钟
    CLK->APBCLK = CLK_APBCLK_TMR0_EN_Msk | CLK_APBCLK_TMR1_EN_Msk | 
    			  CLK_APBCLK_TMR2_EN_Msk | CLK_APBCLK_TMR3_EN_Msk;


解决方案:

经过排查,设备时钟使能库函数使用的定时器2模块(TMR2_MODULE)和定时器3模块(TMR2_MODULE)的值有问题! 如下修改后,使用设备时钟使能函数时,定时器TMR2、TMR3可以正常工作。

原来的值:

#define TMR0_MODULE    ((0x0<<31)|(0x1<<29)    |(0x7<<25)         |( 8<<20)                       |(MODULE_NoMsk<<10)               |CLK_APBCLK_TMR0_EN_Pos)     /*!< TMR0 Module   */
#define TMR1_MODULE    ((0x0<<31)|(0x1<<29)    |(0x7<<25)         |(12<<20)                       |(MODULE_NoMsk<<10)               |CLK_APBCLK_TMR1_EN_Pos)     /*!< TMR1 Module   */
#define TMR2_MODULE    ((0x0<<31)|(0x1<<29)    |(0x7<<25)         |(16<<20)                       |(MODULE_NoMsk<<10)               |CLK_APBCLK_TMR0_EN_Pos)     /*!< TMR2 Module   */
#define TMR3_MODULE    ((0x0<<31)|(0x1<<29)    |(0x7<<25)         |(20<<20)                       |(MODULE_NoMsk<<10)               |CLK_APBCLK_TMR1_EN_Pos)     /*!< TMR3 Module   */

修改后的值:

#define TMR0_MODULE    ((0x0<<31)|(0x1<<29)    |(0x7<<25)         |( 8<<20)                       |(MODULE_NoMsk<<10)               |CLK_APBCLK_TMR0_EN_Pos)     /*!< TMR0 Module   */
#define TMR1_MODULE    ((0x0<<31)|(0x1<<29)    |(0x7<<25)         |(12<<20)                       |(MODULE_NoMsk<<10)               |CLK_APBCLK_TMR1_EN_Pos)     /*!< TMR1 Module   */
#define TMR2_MODULE    ((0x0<<31)|(0x1<<29)    |(0x7<<25)         |(16<<20)                       |(MODULE_NoMsk<<10)               |CLK_APBCLK_TMR2_EN_Pos)     /*!< TMR2 Module   */
#define TMR3_MODULE    ((0x0<<31)|(0x1<<29)    |(0x7<<25)         |(20<<20)                       |(MODULE_NoMsk<<10)               |CLK_APBCLK_TMR3_EN_Pos)     /*!< TMR3 Module   */





声明:[笔记整理] 内容整理自新唐NUC029LAN库函数,版权归原作者所有,若有侵权请联系删除。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是NUC029LAN单片机串口1发送数据到迪文T5系列串口屏并显示的代码: ```c #include <stdio.h> #include "NUC029LAN.h" #define PLLCON_SETTING CLK_PLLCON_50MHz_HXT #define PLL_CLOCK 50000000 #define UART_BAUD_RATE 9600 #define RS485_TX PC12 // 设置RS485为发送模式 #define RS485_RX PC13 // 设置RS485为接收模式 void SYS_Init(void) { SYS_UnlockReg(); CLK->PWRCON &= ~CLK_PWRCON_PD_WAIT_CPU_Msk; // 不等待CPU执行WFI指令 CLK->PLLCON = PLLCON_SETTING; while((CLK->CLKSTATUS & CLK_CLKSTATUS_PLL_STB_Msk) == 0); CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_HCLK_N_Msk) | CLK_CLKDIV_HCLK(1); CLK->CLKSEL0 &= ~CLK_CLKSEL0_HCLK_S_Msk; CLK->CLKSEL0 |= CLK_CLKSEL0_HCLK_S_PLL; CLK->AHBCLK |= CLK_AHBCLK_ISP_EN_Msk; SYS_LockReg(); } void UART_Config(void) { // 打开UART1的时钟 CLK->APBCLK |= CLK_APBCLK_UART1_EN_Msk; // 选择UART1的时钟源为PLL CLK->CLKSEL1 &= ~CLK_CLKSEL1_UART1_S_Msk; CLK->CLKSEL1 |= CLK_CLKSEL1_UART1_S_PLL; // 设置UART1的引脚 SYS->PC_H_MFP &= ~(SYS_PC_H_MFP_PC12_MFP_Msk | SYS_PC_H_MFP_PC13_MFP_Msk); SYS->PC_H_MFP |= SYS_PC_H_MFP_PC12_MFP_UART1_TXD | SYS_PC_H_MFP_PC13_MFP_UART1_RXD; // 配置UART1的波特率 UART1->BAUD = UART_BAUD_RATE; // 配置UART1的数据格式 UART1->LCR = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1; } void RS485_Config(void) { // 设置RS485的引脚 GPIO_SetMode(PC, BIT12, GPIO_MODE_OUTPUT); GPIO_SetMode(PC, BIT13, GPIO_MODE_OUTPUT); // 设置RS485为接收模式 GPIO_SetBit(PC, BIT12); GPIO_SetBit(PC, BIT13); } void UART1_SendByte(uint8_t data) { // 设置RS485为发送模式 GPIO_SetBit(PC, BIT12); GPIO_ClearBit(PC, BIT13); // 发送数据 UART1->THR = data; while(!(UART1->FSR & UART_FSR_TX_EMPTY_Msk)); // 设置RS485为接收模式 GPIO_SetBit(PC, BIT12); GPIO_SetBit(PC, BIT13); } void UART1_SendString(char *str) { while(*str) { UART1_SendByte(*str++); } } int main() { SYS_Init(); UART_Config(); RS485_Config(); while(1) { if(UART1->ISR & UART_ISR_RDA_IF_Msk) { uint8_t data = UART1->RBR; // 将接收到的数据发送到串口屏 UART1_SendByte(data); } } } ``` 这段代码使用了新唐NUC029LAN单片机的UART和GPIO模块,将串口1的数据发送到迪文T5系列串口屏,并将接收到的数据从串口屏显示出来。为了适配RS485通讯,我们还需要通过GPIO控制RS485的接收和发送模式。如果您需要更详细的代码或者有其他问题,请随时联系我。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值