打印
[牛人杂谈]

新唐M0 M4系统初始化

[复制链接]
1174|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
稳稳の幸福|  楼主 | 2019-3-25 13:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
系统初始化包含了时钟(clock)初始化和多功能引脚(Multi Function Pin 简称MFP寄存器)配置。
void SYS_Init(void) {
/* 解锁保护寄存器 */
SYS_UnlockReg();

/*芯片中很多寄存器是写保护的,例如PWRCTL寄存器,要写这些寄存器需要先解锁*/

/* 使能外部高速晶振,一般范围是 (4~24 MHz) */
CLK->PWRCTL |= (0x1 << CLK_PWRCTL_HXT_EN_Pos); // HXT Enabled

/* 等待外部时钟稳定,一般是12M */

CLK_WaitClockReady( CLK_CLKSTATUS_HXT_STB_Msk);

/* HCLK就是CPU 的时钟,切为外部晶振HXT */
CLK->CLKSEL0 = (CLK->CLKSEL0 &~CLK_CLKSEL0_HCLK_S_Msk) | CLK_CLKSEL0_HCLK_S_HXT;

/* 使能UART0和UART1两个IP的时钟 */
CLK->APBCLK |= CLK_APBCLK_UART0_EN;

// UART0 Clock Enable
CLK->APBCLK |= CLK_APBCLK_UART1_EN;


// UART1 Clock Enable
/* 选择UART时钟源 */
CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART_S_Msk) | CLK_CLKSEL1_UART_S_HXT;// 选择外部 12 MHz or 32 KHz 做时钟源
/* Update System Core Clock */

/* 可以通过 SystemCoreClockUpdate() 来自动计算 PllClock, SystemCoreClock 和 CycylesPerUs */

SystemCoreClockUpdate();
/* 初始化 I/O 多功能引脚 */
/* PB13用作UART0 接收,PB14用作UART0发送 */
SYS->PB_H_MFP &= ~(SYS_PB_H_MFP_PB13_MFP_Msk | SYS_PB_H_MFP_PB14_MFP_Msk);

SYS->PB_H_MFP |= (SYS_PB_H_MFP_PB13_MFP_UART0_RX | SYS_PB_H_MFP_PB14_MFP_UART0_TX);

/* PB4用作UART1 RTS,PB5用作UART1接收,PB6用作UART1 发送,PB7用作UART1 CTS */

SYS->PB_L_MFP &= ~(SYS_PB_L_MFP_PB4_MFP_Msk | SYS_PB_L_MFP_PB5_MFP_Msk | SYS_PB_L_MFP_PB6_MFP_Msk | SYS_PB_L_MFP_PB7_MFP_Msk);

SYS->PB_L_MFP |= (SYS_PB_L_MFP_PB4_MFP_UART1_RTS | SYS_PB_L_MFP_PB5_MFP_UART1_RX | SYS_PB_L_MFP_PB6_MFP_UART1_TX | SYS_PB_L_MFP_PB7_MFP_UART1_CTS);

/* 重新加锁 */
SYS_LockReg();

}


使用特权

评论回复
沙发
稳稳の幸福|  楼主 | 2019-3-25 13:22 | 只看该作者
新唐的M0/M4一般都有时钟输出功能,用于调试内部时钟频率,或者产生时钟给其它芯片使用。这个功能引脚一般叫CKO,设定寄存器是FRQDIV
Void CKO_Init() {
/*使能FRQDIV 时钟*/
CLK->APBCLK |= CLK_APBCLK_FDIV_EN_Msk;
/*选择FRQDIV 时钟源为HCLK,从CKO输出的时钟频率将与HCLK有关*/
CLK->CLKSEL2 = (CLK->CLKSEL2&~(CLK_CLKSEL2_FRQDIV_S_Msk))|(CLK_CLKSEL2_FRQDIV_S_HCLK);//CKO using HCLK

/*将P3.6配置为CKO功能*/
SYS->P3_MFP &= ~( SYS_MFP_P36_Msk); SYS->P3_MFP |= (SYS_MFP_P36_CKO);
//HCLK 从P3.6输出 /* CKO 输出的频率为 HCLK/1 */
CLK->FRQDIV = CLK_FRQDIV_DIVIDER1_Msk |

CLK_FRQDIV_DIVIDER_EN_Msk; }


使用特权

评论回复
板凳
稳稳の幸福|  楼主 | 2019-3-25 13:22 | 只看该作者
有的芯片输出的频率至少要/2,那么输出的频率就是HCLK/2了,这个要注意看CLK IP的FRQDIV寄存器的描述。

新唐有些芯片可以用外部32K trim内部HIRC。一般HIRC全温度范围误差2%左右,在有些场合这个精度不够,这时候就可以用外部32K来trim内部HIRC,trim之后HIRC精度可以达到0.25%左右。Trim功能一旦使能就一直在工作,不会停止。如果外部32K晶振出错,trim就会停止,并发生中断。所以需要在中断里面重新启动trim功能。
/*LXT 时钟出错或者尝试次数达到限制将发生中断*/ 
void HIRC_IRQHandler(void) {
uint32_t u32IRCStatus;
/*清除中断标志*/
u32IRCStatus = SYS->IRCTRIMINT;
SYS->IRCTRIMINT = u32IRCStatus;
/*重新启动trim功能*/
SYS->IRCTRIMCTL = SYS_IRCTRIMCTL_LOOP_32CLK| SYS_IRCTRIMCTL_TRIM_12M;
}
/*使能trim功能*/
void SYS_EnableAutoTrim() {
/*取32个32K时钟周期的平均值来trim HIRC*/
SYS->IRCTRIMCTL = SYS_IRCTRIMCTL_LOOP_32CLK| SYS_IRCTRIMCTL_TRIM_12M;
/*一旦出错将发生中断*/
SYS->IRCTRIMIEN = SYS_IRCTRIMIEN_32KERR_EN | SYS_IRCTRIMIEN_FAIL_EN; NVIC_EnableIRQ(HIRC_IRQn);
}



使用特权

评论回复
地板
稳稳の幸福|  楼主 | 2019-3-25 13:23 | 只看该作者
只要调用SYS_EnableAutoTrim就可以使能Auto trim功能来trim HIRC了。

使用特权

评论回复
5
稳稳の幸福|  楼主 | 2019-3-25 13:23 | 只看该作者
新唐的芯片一般有3种复位方式:CPU reset、Chip reset和System reset
 CPU reset:就是将CPU执行指针PC直接指到0的地方重新执行程序
 Chip reset:就是整个芯片复位,类似于POR上电复位的方式,让程序重新执行
 System reset:类似于Chip reset,除了不复位晶振电路和Config Area的值不会重新加载,其它的电路都会被复位
我们常用System reset切到APROM运行,或者切到LDROM运行。系统上电从APROM运行还是从LDROM运行由Config area决定,但是有时侯软件希望切到某个区域运行,这时候用System reset比较好。其实用CPU reset也可以,但是System reset的好处是它会将所有的IP都复位,防止它们在新的程序里面乱动作。

使用特权

评论回复
6
小明的同学| | 2019-3-25 13:30 | 只看该作者
解释的很明白

使用特权

评论回复
7
734774645| | 2019-3-25 20:02 | 只看该作者
初始化是一个大学问

使用特权

评论回复
8
heisexingqisi| | 2019-3-25 20:28 | 只看该作者
多功能引脚配置。

使用特权

评论回复
9
捉虫天师| | 2019-3-25 23:31 | 只看该作者
就是时钟和管脚分配难点。

使用特权

评论回复
10
condition| | 2019-3-26 14:26 | 只看该作者
感谢分享!非常不错的经验

使用特权

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

本版积分规则

187

主题

3282

帖子

8

粉丝