N32905音视频学习笔记-RTC实时时钟

目录

准备工作:

2.软件设计

2.1 内核配置

2.2 RTC应用程序分析

4.编译

5.烧录运行

本例程将在鸭嘴兽wifi音视频开发板上学习操作RTC实时时钟。

准备工作:

wifi音视频开发板一块

1.N32905 RTC简介

N32905内部集成RTC模块,外接32.768KHz的晶振给RTC模块提供时钟源,RTC主要用于给Linux系统提供时间,还可以用于计时和定时。RTC因为是电池供电,当linux系统停止工作后或者掉电,RTC模块仍会继续运行,时间不丢失,依旧还可以给linux提供准确的系统时间。

 

2.软件设计

2.1 内核配置

以下几步操作是在内核配置菜单中选择支持RTC驱动,首先进入/duckbill/N32905/BSP/linux-2.6.17.14_fa93路径,在命令行执行make menuconfig,进入内核配置主菜单,光标移至Device Drivers并按enter键进入下一级菜单。

光标移至Real Time Clock,按enter键进入下一级菜单。

 

选择RTC class、sysfs、proc、dev、Nuvotun W55FA93编译进内核。

最后在命令行输入./build spiramfs,按enter键就开始编译内核,内核生成路径在/duckbill/N32905/BSP/image/Kernel.bin.

2.2 RTC应用程序分析

代码路径:/duckbill/N32905/BSP/applications/rtc/rtc.c。rtc代码如下。

/*
 * RTC(Real Time Clock) application Program
 *
 */

#include <stdio.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <signal.h>

#define RTC_TICK_ON      _IO('p', 0x03)  /* Update int. enable on        */
#define RTC_TICK_OFF     _IO('p', 0x04)  /* ... off                      */
#define RTC_TICK_SET      _IO('p', 0x05)  /* Periodic int. enable on      */
#define RTC_TICK_READ     _IO('p', 0x06)  /* ... off                      */

#define HR24 1
int fd_all=0;

void alarm_func(){

	printf("\n\n*Alarm interrupt come on,the func running!*\n");

	}

void ctrl_c_signal (int sig)
{
  switch (sig){
  	printf("/n/n **You have input 'ctrl+c',so must be input 'X' exit DEMO!\n\n");
  case SIGTERM: 

  case SIGINT:
/* Disable alarm interrupts */
		ioctl(fd_all, RTC_AIE_OFF, 0);
		ioctl(fd_all, RTC_TICK_OFF, 0);
	  close(fd_all);
	  
    return ;
    break;
  default:
  	
    printf ("What?\n");
  }
}
	


//函数功能:设置当前RTC时间
//输入参数:fd:RTC文件描述符
//返回值:空
void setup_time(int fd){

int i,retval;
unsigned long tmp, data;
struct rtc_time rtc_tm;
int scale_type = HR24;
struct rtc_wkalrm rtc_alarmtm;
int ret;	
static char year[4], month[4],day[4],hour[4],min[4],sec[4];
printf("Input the adjust time:\n");
printf("You should input 6 words,and must be 'enter' per word!\n");
printf("->year->month->day->hour->min->sec\n");

scanf("%s %s %s %s %s %s", year, month,day,hour,min,sec); 	//获取年月日时分秒

printf("You input the time is:%s/%s/%s/ %s:%s:%s\n\n", year, month,day,hour,min,sec); 
	
  rtc_tm.tm_year = atoi(year) - 1900;			//依次将年月日时分秒赋值给结构体rtc_tm
  rtc_tm.tm_mon = atoi(month) - 1;
  rtc_tm.tm_mday = atoi(day);
  rtc_tm.tm_hour = atoi(hour);
  rtc_tm.tm_min = atoi(min);
  rtc_tm.tm_sec = atoi(sec);
  
retval = ioctl(fd, RTC_SET_TIME, &rtc_tm);		//设置RTC,RTC时间将更新
if (retval <0) {
	printf("ioctl RTC_SET_TIME  faild!!!\n");
	return ;
}

/*print current time*/
printf("Adjust current RTC time as: %04d-%02d-%02d %02d:%02d:%02d\n\n",
	   rtc_tm.tm_year + 1900,
	   rtc_tm.tm_mon + 1,
	   rtc_tm.tm_mday,
	   rtc_tm.tm_hour,
	   rtc_tm.tm_min,
	   rtc_tm.tm_sec);
printf("Adjust current RTC time test OK!\n");
}	

//函数功能:读取当前RTC时间
//输入参数:fd:RTC文件描述符
//返回值:空		
void read_time(int fd){

int i,retval;
unsigned long tmp, data;
struct rtc_time rtc_tm;
int scale_type = HR24;
struct rtc_wkalrm rtc_alarmtm;
	
/*read current time*/

retval=ioctl(fd,RTC_RD_TIME,&rtc_tm);		//读取RTC时间,保存在结构体rtc_tm中
if (retval <0) {
	printf("ioctl RTC_RD_TIME  faild!!!\n");
	return ;
}
/*print current time*/
printf("Read current RTC time is: %04d-%02d-%02d %02d:%02d:%02d\n\n",
	   rtc_tm.tm_year + 1900,
	   rtc_tm.tm_mon + 1,
	   rtc_tm.tm_mday,
	   rtc_tm.tm_hour,
	   rtc_tm.tm_min,
	   rtc_tm.tm_sec);
printf("Read current RTC time test OK!\n");
}	

//函数功能:设置RTC闹钟时间
//输入参数:fd:RTC文件描述符
//			sec:RTC闹钟时间,即sec秒后,RTC产生中断信号
//			void(*func)():函数指针
//返回值:空		
void setup_wkalarm(int fd,int sec,void(*func)()){
	
int i,retval;
unsigned long tmp, data;
struct rtc_time rtc_tm;
int scale_type = HR24;
struct rtc_wkalrm rtc_alarmtm;

/*read current time*/

retval=ioctl(fd,RTC_RD_TIME,&rtc_tm);		//读取RTC时间,保存在结构体rtc_tm中
if (retval <0) {
	printf("ioctl RTC_RD_TIME  faild!!!\n");
	return ;
}

printf("read current time is: %04d-%02d-%02d %02d:%02d:%02d\n\n",
	   rtc_tm.tm_year + 1900,
	   rtc_tm.tm_mon + 1,
	   rtc_tm.tm_mday,
	   rtc_tm.tm_hour,
	   rtc_tm.tm_min,
	   rtc_tm.tm_sec);
	   
    rtc_tm.tm_sec = rtc_tm.tm_sec+sec;//设置5s的闹钟时间,5s时间一到,RTC中断触发
    if (rtc_tm.tm_sec>60)
    	{
    		rtc_tm.tm_sec=rtc_tm.tm_sec-60;
    		rtc_tm.tm_min=rtc_tm.tm_min+1;
    		}
    		
    rtc_alarmtm.enabled=1;			//RTC闹钟使能
    rtc_alarmtm.time=rtc_tm;		//给闹钟时间赋值

/* Set the alarm to 5 sec in the future */

retval = ioctl(fd, RTC_WKALM_SET, &rtc_alarmtm);	//设置RTC闹钟时间
if (retval <0) {
	printf("ioctl RTC_ALM_SET  faild!!!\n");
	return ;
}

/* Read the current alarm settings */

retval = ioctl(fd, RTC_WKALM_RD, &rtc_alarmtm);		//读取当前的闹钟时间
if (retval <0) {
	printf("ioctl  RTC_ALM_READ faild!!!\n");
	return ;
}

rtc_tm=rtc_alarmtm.time;

printf("read current alarm time is: %04d-%02d-%02d %02d:%02d:%02d\n\n",
	   rtc_tm.tm_year + 1900,
	   rtc_tm.tm_mon + 1,
	   rtc_tm.tm_mday,
	   rtc_tm.tm_hour,
	   rtc_tm.tm_min,
	   rtc_tm.tm_sec);

/* Enable alarm interrupts */

retval = ioctl(fd, RTC_AIE_ON, 0);		//使能RTC中断
if (retval <0) {
	printf("ioctl  RTC_AIE_ON faild!!!\n");
	return ;
}

fprintf(stderr, "Waiting %d seconds for wkalarm...\n\n",sec);
fflush(stderr);

/* This blocks until the alarm ring causes an interrupt */
retval = read(fd, &data, sizeof(unsigned long));		//read函数阻塞,直到有数据可读
if (retval >0) {
	func();										//5s闹钟时间到,执行func函数
}else{
	printf("!!!alarm faild!!!\n");
	return ;
		}
/* Disable alarm interrupts */
retval = ioctl(fd, RTC_AIE_OFF, 0);			//关闭闹钟中断
if (retval == -1) {
	printf("ioctl RTC_AIE_OFF faild!!!\n");
	return ;
}

printf("Test week alarm(hour,min,sec) test OK!\n");		
}

int main(void) {

int i, fd, retval, irqcount = 0;
unsigned long tmp, data;
struct rtc_time rtc_tm;
int scale_type = HR24;
struct rtc_wkalrm rtc_alarmtm;
unsigned int select;
printf("RTC Sample\n");
fd = open ("/dev/rtc", O_RDONLY);	//打开RTC
fd_all=fd;
if (fd<0) {
printf("open rtc faild!!!\n");
return ;
}
signal (SIGTERM, ctrl_c_signal); /* for the TERM signal.. */ 
signal (SIGINT, ctrl_c_signal); /* for the CTRL+C signal.. */



      printf("\n******** RTC Test Demo ***********\n");
      printf("1.Read current RTC time ..\n");
      printf("2.Adjust current RTC time ..\n");
      printf("3.Test week alarm(year,mon,day)..\n");     
      printf("X.Exit(don't use 'ctrl+c',must be 'X')..\n");
      printf("**************************************\n");
      printf("Select : \n");   


 while(1)
    {
 
      select = getchar();

  switch(select) 
    	{
	case 0x31:
	  read_time(fd);		//读取当前RTC时间
	  break;
	  
	case 0x32:
	  setup_time(fd);		//设置当前RTC时间
	  break;
	  
	case 0x33:
	  setup_wkalarm(fd,5,alarm_func);		//设置RTC定时5s
	  break;	  
	case 0x58: //'x' -- exit the program    		
	case 0x78: //'X'    			
	  printf("haha-goto the end now.\n");
	  goto end; 

	default :
	  printf("\n\n\t==>Select command number(1-3) \n");
	  break;	
    	}
    }
end:

close(fd);			//关闭RTC
return 0;

} /* end main */

Main函数一进来打印菜单,提示用户输入选择,1代表读RTC时间,2代表设置RTC时间,3代表设置RTC闹钟时间。

读RTC时间:调用系统函数ioctl读RTC时间到结构体rtc_time。

设置RTC时间:把你想设置的时间填充到RTC结构体rtc_time,调用系统函数ioctl就更新RTC时间了。

设置RTC闹钟时间:首先调用系统函数ioctl读当前RTC时间到结构体rtc_time里,在当前RTC时间上修改时间,就得到了闹钟时间。调用系统函数ioctl设置闹钟时间,使能RTC中断,接下来通过read函数等待中断到来,一旦触发就执行中断服务程序func()。

4.编译

在ubuntu下切换路径至/duckbill/N32905/applications/rtc/。

执行make,编译生成可执行文件rtc_demo,rtc_demo将会自动拷贝至例程文件系统目录 /duckbill/N32905/usr/TEST_mini905/mkFilesys下。

执行例程文件系统TEST_mini905/test_mini905/目录下的脚本mkjffs2.sh,生成我们所需的jffs2文件系统。

5.烧录运行

WIFI-Mini905开发板与电脑之间连接好usb电源线(也充当下载线)、usb转串口线,将拨码开关S1拨向Rec位,按下自锁开关K1,开发板通电,N32905进入烧录模式。

使用TurboWriter依次烧录 开发板光盘资料\Mini905光盘资料\BIN\基础例程下的loader(SpiLoader_905.bin)、内核(Kernel.bin)以及刚刚生成的文件系统(TEST_mini905.jffs2.summary),烧录步骤与例程1一致。

烧录完成后将拨码开关S1拨向Nor位,开发板重新通电,电源指示灯亮,N32905进入正常启动模式,等待系统运行起来。

在串口超级终端输入./rtc_demo,执行RTC应用程序。

选择1,读取当前RTC时间,由于WIFI-Mini905开发板未带电池,每次断电后用户设置的RTC时间将会丢失,将会回到默认时间2005-01-01。

选择2,设置RTC时间,我这里设置的是2014-12-8,22-55-0。

选择3,设置闹钟时间,我这里设置5s后RTC触发中断。

 

猜你喜欢

转载自blog.csdn.net/chenzhe805/article/details/81707570