S3C2440之设置系统时钟

33 篇文章 1 订阅

任何一个ARM初始化的时候一般都会优先设置系统时间,尤其是在设置一些与系统时钟息息相关的外设的时候,

S3C2440也不例外,系统时钟设置如下:

/******************************
*文件名:clock.c			  *
*功能:   电子钟     		  *
*创建者: 潘星宇				  *
*最后修改:2013.03.7 		  *
*备注:						  *
*							  *
*******************************/
#include "clock.h"

static U32 UPLL;
/*****************************************************************************
***函数名:cal_cpu_bus_clk()
***功能:读取系统时钟值,提供给别的外设使用
***参数:无
***返回:无
*****************************************************************************/
void cal_cpu_bus_clk(void)  
{
	U32 val;
	U8 m, p, s;
	
    /*从寄存器MPLLCON中提取MDIV,PDIV,SDIV的值,从而计算FCLK的值,
	就是MPLLout	val = rMPLLCON;	*/
 	val = rMPLLCON;
	m = (val>>12)&0xff;	//注意,之前在调用函数中已经设置好了rMPLLCON的值
	p = (val>>4)&0x3f;  //p=PDIV=MPLLCON[9:4] 6位取值
	s = val&3;		    //s=SDIV=MPLLCON[1:0] 低2位取值

	/*(m+8)*FIN*2 不要超出32位数! //(1<<s)表示第s位置1,也就是2^s.
	 公式MPLL=(2*(MDIV+8)*FIN)/((PDIV+2)*(2^s)) FIN=12000000*/
	FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;

    /*从寄存器CLKDIVN中提取出HDIVN和PDIVN,进行FCLK:HCLK:PCLK分频比的设置*/
	val = rCLKDIVN;		   //在调用函数里面已经设置了rCLKDIVN的值
	m = (val>>1)&3;	       //从寄存器CAMDIVN中提取出CAMDIVN[9:8]
	p = val&1;			   //在调用函数里面已经设置了rCAMDIVN的值
	val = rCAMDIVN;		   //s[1:0]=CAMDIVN[9:8]=HCLK4_HALF,HCLK3_HALF

	/*s[4]=CAMDIVN[12]=DVS_EN,如果DVS_EN=1,则CPU时钟为HCLK,否则为FCLK*/
	s = val>>8;	
	
	switch (m) {		   //这里的m=HDIVN,对FCLK和HCLK进行分频设置
	case 0:
		HCLK = FCLK;
		break;
	case 1:
		HCLK = FCLK>>1;	    //HCLK=FCLK/2

		break;
	case 2:
		if(s&2)			     //如果s[1]=1,也即CAMDIVN[9]=HCLK4_HALF=1
			HCLK = FCLK>>3;	 //HCLK=FCLK/8

		else
			HCLK = FCLK>>2;	 //HCLK=FCLK/4

		break;
	case 3:
		if(s&1)				 //如果s[0]=1,也即CAMDIVN[8]=HCLK3_HALF=1
			HCLK = FCLK/6;	 //HCLK=FCLK/6

		else
			HCLK = FCLK/3;	 //HCLK=FCLK/3
		break;
	}
	
	if(p)					 //这里p=PDIVN,对HCLK和PCLK进行分频设置
		PCLK = HCLK>>1;		 //PDIVN=1,则PCLK=HCLK/2;否则PCLK=HCLK
	else
		PCLK = HCLK;		 //如果s[4]=1,也即CAMDIVN[12]=DVS_EN=1
		
	val = rUPLLCON;	         //读ytfrUPLLCON的值
	m = (val>>12)&0xff;	     //m=MDIV=UPLLCON[19:12] 8位
	p = (val>>4)&0x3f;	     //p=PDIV=UPLLCON[9:4] 6位
	s = val&3;	             //s=SDIV=UPLLCON[1:0] 2位

	/*公式UPLL=((MDIV+8)*FIN)/((PDIV+2)*(2^s)) FIN为输入时钟频率*/
	UPLL = ((m+8)*FIN)/((p+2)*(1<<s));	

	/*如果CLKDIVN[3]=1,则UPLL需要分频*/
	UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;	 
}

/**************************************************************************
***** 函数名:  clock(void)
***** 功能:	电子钟
***** 参数:    无
***** 返回值:	无
***** 创建者:	潘星宇
***** 创建时间: 2013-03-5
***** 最后更新:2013-03-7
****************************************************************************/
void clock(void)
{
	static U8 str[30] = {0};		   //串口寄存数组
	U8 ch;				               //串口用变量
	static U8 UART_i = 0; 			   //串口数组计数用
	U8 hour_i;		                   //画小时刻度计数用的变量
	U8 minute_i;			           //画分钟刻度计数用的变量
	U32 hour;				           //从RTC读取的小时
	U32 minute;				           //分钟
    U32 second;				           //秒
	U32 second_ch;                     //秒控制变量,用于控制每秒才显示一次
	static U32 hour_register;		   //小时寄存器,用于储存上一次画时针的位置,用于清屏
	static U32 minute_register;		   //分钟寄存器
	static U32 second_register;		   //秒寄存器

	Brush_Background(0x435c);          //绘制背景品蓝色
	RTC_time_set (0x13, 0x03, 0x07, 0x04, 0x14, 0x55, 0x35);

 	draw_circle(180,136,123,0xfea0);   //表外框金黄色

//绘制返回
	draw_return(400, 130, COLOR_BLACK, COLOR_LIGHT_GREEN);	//背景浅绿色

	/**********************************************
	 *已知起始点、两点距离和角度画线的参数分别为:*
	 *第一点坐标x1,y1;							  *
	 *长度;									  *
	 *角度(不是弧度);							  *
	 *颜色;                                      *
	 *希望保留起始的点的个数;					  *
	 *希望保留最后的点的个数                      *
	 **********************************************/
	//画小时刻度
	for (hour_i=0; hour_i<12; hour_i++)
	{
		one_point_to_another(180, 136, 120, hour_i*30, 0xfb00, 0, 15);    //从0点画到11点 橙色
	}

	//画分钟刻度
	for (minute_i=0; minute_i<60; minute_i++)
	{
		if (minute_i % 5)				       //整点处不画刻度
		{
			one_point_to_another(180, 136, 120, minute_i*6, 0xfc00, 0, 1 );	//从1分画到59分 橘黄色
		}
	}

	while (function_flag==0)
	{
		hour = rBCDHOUR;    //获取小时
		minute = rBCDMIN;   //获取分钟
		second = rBCDSEC;   //获取秒
		hour = ((hour / 16)*10 + hour % 16) % 12;//由于从RTC读出的都是16进制的,先转成10进制,再将24小时格式转化为12小时格式
		minute = (minute / 16)*10 + minute % 16; 	   
		second = (second / 16)*10 + second % 16;	    				     
		if (second != second_ch)
		{
			//先清除掉上次画的时针,分针,秒针,长度暂分别定为35,60,90
			if ((hour_register*30 + (minute_register / 10)*5) != (hour*30 + (minute / 10)*5)) //为了消除分针和时针闪屏的问
			{																				  //只有当分针或时针确实移动了位置才消除上一次画的的值
				one_point_to_another(180, 136, 120, hour_register*30 + (minute_register / 10)*5, 0x435c, 35, 0);	 
			}
			if (minute_register != minute)
			{
				one_point_to_another(180, 136, 120, minute_register*6, 0x435c, 60, 0);	
			}
 			one_point_to_another(180, 136, 120, second_register*6, 0x435c, 90, 0);

			second_ch = second;      //使秒控制变量等于当前时钟的秒值,这样直到秒变化,才再次进入这个内部来
			one_point_to_another(180, 136, 120, hour*30 + (minute /10)*5, COLOR_BLACK, 35, 0);	  //时针每小时走30°,分钟动10分钟,时钟动5°
			one_point_to_another(180, 136, 120, minute*6, 0x001f, 60, 0);  //蓝色
			one_point_to_another(180, 136, 120, second*6, 0xf800, 90, 0);  //红色
			rtc_display_lcd(320,150,0xb1dd,0x08a8); //显示电子钟,参数分别为横坐标、纵坐标、颜色、背景色
			hour_register = hour;	             //将时分秒的值储存起来,用于下一秒清除上一秒的变化
			minute_register = minute;
			second_register = second;
		}
		
		while (rUTRSTAT0 & 0x1)			  //当串口接收缓冲器有数据时
		{
			ch = rURXH0;				  //接收数据
			str[UART_i++] = ch;
			if((ch == 0xff)||(UART_i == 29 ))	  //接收数据完成
			{
				RTC_time_set (str[0], str[1], str[2], str[3], str[4], str[5], str[6]);
				UART_i = 0;
   			}
		}
	}
}


附送一部分电子时钟的代码,头文件如下:

#ifndef CLOCK_H
#define CLOCK_H
#include "LCD.h"
#include "zi.h"
#include "global_value.h"
#include "2440addr.h"
#include "RTC.h"
#include "interface.h"
#include "common_functions.h"
/*****************************************************************************
***函数名:cal_cpu_bus_clk()
***功能:读取系统时钟值,提供给别的外设使用
***参数:无
***返回:无
*****************************************************************************/
extern void cal_cpu_bus_clk(void); 

/**************************************************************************
***** 函数名:  clock(void)
***** 功能:	电子钟
***** 参数:    无
***** 返回值:	无
***** 创建者:	潘星宇
***** 创建时间: 2013-03-5
***** 最后更新:2013-03-7
****************************************************************************/
extern void clock(void); 
#endif

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值