打印
[Cortex-M0技术交流]

菜鸟学习M0第十八帖——RTC续(通过串口可设置时间及闹钟)

[复制链接]
3134|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 lixiaoxu2meng 于 2011-9-27 11:20 编辑

当时发了个RTC的帖子不过是基于 半主机模式的 当时没多想  经过菜农老师的提醒: 说如何进行时间校准呢 于是我将半主机模式改为利用串口 来进行时间校准 初步已经可以设置 时间及闹钟了  
如果想进行时间校准 向下位机发送 a 然后按照提示 逐个 进行设置 然后输入 b结束
如果想进行闹钟设置 向下位机发送 c然后按照提示 逐个 进行设置 然后输入 d结束
功能是实现了 但是自己感觉不太满意 无论是功能还是程序结构 等有时间进行进一步的完善 还请一起学的兄弟们多多指教
main函数
/*---------------------------------------------------------------------------------------------------------*/
/* */
/* Copyright(c) 2011 Nuvoton Technology Corp. All rights reserved. */
/* */
/*---------------------------------------------------------------------------------------------------------*/
#include "includes.h" //包含所需的头文件
S_DRVRTC_TIME_DATA_T Curren_Time;
int32_t AD_Value;
/*************************************************************************************
** Function name: main
** Descriptions: 本函数实现:RTC功能及闹钟 (同时也包括:AD温度模块 按键模块 串口模块 定时器模块 GPIO模块 LED数码管显示模块)
相当一个大杂烩吧
** input parameters: 无
** output parameters: 无
** Returned value: 无
*************************************************************************************/
int main (void)
{
uint8_t i;
Set_System(); //封装一些初始化模块
printf("======RTC实验=====\n");
while(1)
{
if(ID == 1)//查询是否去RTC时间
{
ID = 0;
DrvRTC_Read(DRVRTC_CURRENT_TIME, &Curren_Time);
DrvADC_StartConvert(); // 开启ADC转换
while(DrvADC_IsConversionDone()==FALSE); // 判断ADC是否转换结束 并送串口显示
AD_Value = DrvADC_GetConversionData(7);
AD_Value = AD_Value*3300/4095- 730; // 将电压值转换成温度 经过校准后 确认0度为730mv左右
AD_Value = AD_Value/-2;

printf("当前日期为: %d年%d月%d日 星期%d\n",Curren_Time.u32Year,Curren_Time.u32cMonth,Curren_Time.u32cDay,Curren_Time.u32cDayOfWeek);

printf("当前时间为: %d:%d:%d\n",Curren_Time.u32cHour,Curren_Time.u32cMinute,Curren_Time.u32cSecond);
printf("当前温度为: %d度\n",AD_Value);
}
if(ID == 4)
{
ID = 0;
for(i=0;i<14;i++)
{
Adjust = DATE;
}
RTC_Configuration();
}
if(ID == 5)
{
ID = 0;
for(i=0;i<14;i++)
{
Alarm = DATE;
}
RTC_Configuration();
}
KeyCode = GetKey();
switch(KeyCode)
{
case KEY1_DOWN_USER:
{
DrvGPIO_ClrBit(E_GPB,10); //关闭蜂鸣器
}
break;
case KEY2_DOWN_USER:
{
DrvGPIO_SetBit(E_GPB,10); //开启蜂鸣器
}
break;
default:break;
}
}
}


hw_config函数
#include "includes.h" //包含所需的头文件

/*************************************************************************************
** Function name: Set_System
** Descriptions: 封装一些初始化模块
** input parameters: count
** output parameters: 无
** Returned value: 无
*************************************************************************************/
void Set_System(void)
{
RCC_Configuration(); //配置系统时钟

InitButtonVar(); //按键初始化

GPIO_Configuration(); //配置GPIO

USART_Configuration(); //配置USART

ADC_Configuration(); //配置ADC

TIMER_Configuration(); //配置TIMER

RTC_Configuration(); //配置RTC
}
/*************************************************************************************
** Function name: RCC_Configuration
** Descriptions: 系统时钟源设置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void RCC_Configuration(void)
{
UNLOCKREG(); // 对写保护位操作时 需要一次向0x50000 0100写入 0x59,0x16,0x88,
DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);// 与其 SYSCLK->WRCON.XTL12M_EN = 1; 等同
// PWRCON寄存器(这些寄存器在上电复位到用户解锁定之前是锁定的)除了 BIT[6]位其他位都受写保护
// 解除这些需要向 0x50000 0100写入 0x59,0x16,0x88,
// 令PWRCON寄存器的BITP[0]为1(即设定12M外部晶振)
delay_ms(100); // while (DrvSYS_GetChipClockSourceStatus(E_SYS_XTL12M) != 1);//等待外部12MHZ晶振就绪
LOCKREG(); // 向“0x5000_0100”写入任何值,就可以重锁保护寄存器
}
/*************************************************************************************
** Function name: GPIO_Configuration
** Descriptions: GPIO配置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void GPIO_Configuration()
{
DrvGPIO_Open( E_GPB, 0, E_IO_INPUT ); //RX
DrvGPIO_Open( E_GPB, 1, E_IO_OUTPUT ); //TX

DrvGPIO_Open( E_GPB, 14, E_IO_INPUT ); //按键端口设置为输入
DrvGPIO_Open( E_GPB, 15, E_IO_INPUT );

DrvGPIO_Open( E_GPB, 10, E_IO_OUTPUT );//蜂鸣器引脚设置为输出
DrvGPIO_ClrBit(E_GPB,10); //关闭蜂鸣器

DrvGPIO_Open( E_GPA, 2, E_IO_OUTPUT );//数码管段选
DrvGPIO_Open( E_GPA, 3, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 4, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 5, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 6, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 7, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 8, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 9, E_IO_OUTPUT );
DrvGPIO_Open( E_GPC, 14, E_IO_OUTPUT );//数码管位选
DrvGPIO_Open( E_GPC, 15, E_IO_OUTPUT );
DrvGPIO_Open( E_GPC, 6, E_IO_OUTPUT );
DrvGPIO_Open( E_GPC, 7, E_IO_OUTPUT );
}
/*************************************************************************************
** Function name: USART_Configuration
** Descriptions: USART配置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void USART_Configuration()
{
STR_UART_T param;
DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC, 0); //使用外设时注意必须设置该外设的时钟 设置USART的时钟源为外部12MHZ
DrvGPIO_InitFunction(E_FUNC_UART0); // 复用功能引脚设置
param.u32BaudRate = 9600; // 波特率 9600
param.u8cDataBits = DRVUART_DATABITS_8; // 数据位
param.u8cStopBits = DRVUART_STOPBITS_1; // 停止位
param.u8cParity = DRVUART_PARITY_NONE; // 校验位
param.u8cRxTriggerLevel = DRVUART_FIFO_1BYTES; // FIFO存储深度 1 字节
param.u8TimeOut = 0; // FIFO超时设定
DrvUART_Open(UART_PORT0, ¶m); // 串口usart0开启、结构体整体赋值
DrvUART_EnableInt(UART_PORT0, DRVUART_RDAINT,UART_INT_HANDLE);// 使能串口1接收中断并建立一个中断回调函数
}
/*************************************************************************************
** Function name: UART_INT_HANDLE
** Descriptions: 串口接收中断
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void UART_INT_HANDLE (uint32_t u32IntStatus)
{
static uint8_t step = 0;
uint8_t buffer[1]={0xFF};
if(u32IntStatus & DRVUART_RDAINT) //如果是接收中断
{
if(UART0->ISR.RDA_IF==1) //如果是串口0接收中断
{
if(ID == 0)
{
DrvUART_Read(UART_PORT0,buffer,1);
if(buffer[0] == 97) //输入'a'进行时间校准
{
ID = 2;
printf("请输入要校准的日期及时间: \n");
printf("请逐个输入两位年份:\n");
step = 0;
}
else if(buffer[0] == 99) //输入'c'进行闹钟设置
{
ID = 3;
printf("请输入闹钟需要设置的日期及时间: \n");
printf("请逐个输入两位年份:\n");
step = 0;
}
}
else if(ID >= 2)
{
switch(step)
{
case 0:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[0] = buffer[0] - 0x30;
step = 1;
break;
case 1:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[1] = buffer[0] - 0x30;
printf("请逐个输入两位月:\n");
step = 2;
break;
case 2:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[2] = buffer[0] - 0x30;
step = 3;
break;
case 3:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[3] = buffer[0] - 0x30;
printf("请逐个输入两位日:\n");
step = 4;
break;
case 4:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[4] = buffer[0] - 0x30;
step = 5;
break;
case 5:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[5] = buffer[0] - 0x30;
printf("请逐个输入两位时:\n");
step = 6;
break;
case 6:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[6] = buffer[0] - 0x30;
step = 7;
break;
case 7:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[7] = buffer[0] - 0x30;
printf("请逐个输入两位分:\n");
step = 8;
break;
case 8:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[8] = buffer[0] - 0x30;
step = 9;
break;
case 9:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[9] = buffer[0] - 0x30;
printf("请逐个输入两位秒:\n");
step = 10;
break;
case 10:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[10] = buffer[0] - 0x30;
step = 11;
break;
case 11:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[11] = buffer[0] - 0x30;
step = 12;
printf("请输入星期:\n");
//printf("请输入b结束:\n");
break;
case 12:
DrvUART_Read(UART_PORT0,buffer,1);
DATE[12] = buffer[0] - 0x30;
step = 13;
if(ID == 2)
printf("请输入b结束时间校准:\n");
else if(ID == 3)
printf("请输入d结束闹钟设置:\n");
break;
case 13:
DrvUART_Read(UART_PORT0,buffer,1);
if(buffer[0] == 98)
ID = 4;
else if(buffer[0] == 100)
ID = 5;
break;
case 14:
break;
case 15:
break;
case 16:
break;
case 17:
break;

default:break;
}
}
}
}


}
/*************************************************************************************
** Function name: ADC_Configuration
** Descriptions: 配置USART
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void ADC_Configuration()
{
DrvSYS_SelectIPClockSource(E_SYS_ADC_CLKSRC, 0); //使用外设时注意必须设置该外设的时钟 设置ADC的时钟源为外部12MHZ
DrvADC_Open(ADC_SINGLE_END, ADC_SINGLE_OP, 0, EXTERNAL_12MHZ, 3); // ADC_SINGLE_END AD为单端输入模式
// ADC_SINGLE_OP 单一转换
// 1 GA0作为输入 模式输入通道使能
// EXTERNAL_12MHZ ADC时钟为 外部12MHZ
// 3 AD时钟频率 = ADC时钟/(3+1) = 3MHZ
DrvADC_SetADCChannel(0x10,ADC_SINGLE_END); // 8 设置为模拟通道7
// ADC_SINGLE_END AD为单端输入模式
ADC->ADCR.DMOF = 0; //转化结果无符号
ADC->ADCHER.PRESEL = 0x02; //内部温度传感器
ADC->ADCHER.CHEN = 0x80; //模拟输入通道7使能
SYS->TEMPCR = 0x01; //使能温度传感器

}
/*************************************************************************************
** Function name: TIMER_Configuration
** Descriptions: TIMER配置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void TIMER_Configuration()
{
DrvTIMER_Init(); //初始化定时器

DrvSYS_SelectIPClockSource(E_SYS_TMR0_CLKSRC,0); //使用外设时注意必须设置该外设的时钟 设置TIMER0的时钟源为外部12MHZ

DrvTIMER_Open(E_TMR0,1000,E_PERIODIC_MODE); //设定定时器timer0的tick周期,并且启动定时器:定时器通道 TMR0 每秒1000次 周期模式

DrvTIMER_SetTimerEvent(E_TMR0,5,(TIMER_CALLBACK) Timer0_Callback,0); //安装一个定时处理事件到 timer0通道

DrvTIMER_EnableInt(E_TMR0); //使能定时器中断 //TIMER0->TCSR.IE = 1

DrvTIMER_Start(E_TMR0); //定时器timer0开始计数 //TIMER0->TCSR.CEN = 1;
}
/*************************************************************************************
** Function name: Timer0_Callback
** Descriptions: 定时处理事件,LED动态扫描
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void Timer0_Callback (void)
{

static uint8_t count= 0;
static uint8_t count1= 0;
static uint8_t i,xx[4];
uint32_t data;
uint16_t ValueBuff ;
ValueBuff = value;
KeyPro(); //按键扫描 该函数在 button.c 中实现
count++;
count1++;
if(count1>=100)
{
count1 = 0;
if(ID == 0)
ID = 1; //每500ms 将获取RTC时间的标志置一
}
if(count >= 5)
count = 1;
for(i=0;i<4;i++)
{
xx = ValueBuff%10;
ValueBuff = ValueBuff/10;
}
switch(count)
{
case 1:
DrvGPIO_SetBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,6);
DrvGPIO_ClrBit(E_GPC,7);
data = Table[xx[0]]<<2;
GPIOA->DOUT = data;
break;
case 2:
DrvGPIO_SetBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,6);
DrvGPIO_ClrBit(E_GPC,7);
data = Table[xx[1]]<<2;
GPIOA->DOUT = data;
break;
case 3:
DrvGPIO_SetBit(E_GPC,7);
DrvGPIO_ClrBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,6);
data = Table[xx[2]]<<2;
GPIOA->DOUT = data;
break;
case 4:
DrvGPIO_SetBit(E_GPC,6);
DrvGPIO_ClrBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,7);
data = Table[xx[3]]<<2;
GPIOA->DOUT = data;
//DrvGPIO_ClrBit(E_GPA,9); //显示小数点
break;
default:break;
}
}
/*************************************************************************************
** Function name: RTC_Configuration
** Descriptions: RTC配置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void RTC_Configuration()
{
UNLOCKREG();
/* Step 1. Enable and Select RTC clock source */
SYSCLK->WRCON.XTL32K_EN = 1;//Enable 32Khz for RTC clock source
SYSCLK->APBCLK.RTC_EN =1;//Enable RTC clock source
LOCKREG();
/* Step 2. Initiate and unlock RTC module */
START_RTC();
/* Step 3. Initiate Time and Calendar setting */
RTC->TSSR.HR24 =Adjust[13];//Set 24hour mode
RTC->DWR.DWR =Adjust[12];//Set Sunday
//Set time and calendar for loading register, Calendar: 11/9/18, Time: 12:58:00
Set_CLR(Adjust[0],Adjust[1],Adjust[2],Adjust[3],Adjust[4],Adjust[5]);//设置日期载入寄存器CLR
Set_TLR(Adjust[6],Adjust[7],Adjust[8],Adjust[9],Adjust[10],Adjust[11]);//设置时间载入寄存器TLR
/* Step 4. Set alarm interrupt */
//Set time and calendar for alarm register , Calendar: 11/9/18, Time: 13:10:00
Set_CAR(Alarm[0],Alarm[1],Alarm[2],Alarm[3],Alarm[4],Alarm[5]);//设置日历闹钟寄存器CAR
Set_TAR(Alarm[6],Alarm[7],Alarm[8],Alarm[9],Alarm[10],Alarm[11]);//设置时间闹钟寄存器TAR
DrvRTC_EnableInt(DRVRTC_ALARM_INT, RTC_AlarmCallBackfn); //闹钟中断使能 并设置中断回调函数
}
/*************************************************************************************
** Function name: RTC_AlarmCallBackfn
** Descriptions: 闹钟中断函数
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void RTC_AlarmCallBackfn()
{
DrvGPIO_SetBit(E_GPB,10); //开启蜂鸣器
}
/*************************************************************************************
** Function name: START_RTC
** Descriptions: 启动RTC
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void START_RTC(void)
{
while(1)
{
RTC->INIR = 0xa5eb1357; //RTC初始化
if(inpw(&RTC->INIR)==1)
break;
}
while(1)
{
RTC->AER.AER = 0xA965; //RTC读/写使能
if(inpw(&RTC->AER)&0x10000)// AER bit
break;
}
}
/*************************************************************************************
** Function name: Set_TLR
** Descriptions: 设置RTC的TLR寄存器
** input parameters: int32_t a,int32_t b,int32_t c,int32_t d,int32_t e,int32_t f
** output parameters: none
** Returned value: none
*************************************************************************************/
void Set_TLR (int32_t a,int32_t b,int32_t c,int32_t d,int32_t e,int32_t f)
{
outpw(&RTC->TLR, a<<20|b<<16|c<<12|d<<8|e<<4|f) ;
}
/*************************************************************************************
** Function name: Set_CLR
** Descriptions: 设置RTC的CLR寄存器
** input parameters: int32_t a,int32_t b,int32_t c,int32_t d,int32_t e,int32_t f
** output parameters: none
** Returned value: none
*************************************************************************************/
void Set_CLR (int32_t a,int32_t b,int32_t c,int32_t d,int32_t e,int32_t f)
{
outpw(&RTC->CLR, a<<20|b<<16|c<<12|d<<8|e<<4|f) ;
}
/*************************************************************************************
** Function name: Set_TAR
** Descriptions: 设置RTC的TAR寄存器
** input parameters: int32_t a,int32_t b,int32_t c,int32_t d,int32_t e,int32_t f
** output parameters: none
** Returned value: none
*************************************************************************************/
void Set_TAR(int32_t a,int32_t b,int32_t c,int32_t d,int32_t e,int32_t f)
{
outpw(&RTC->TAR, a<<20|b<<16|c<<12|d<<8|e<<4|f) ;
}
/*************************************************************************************
** Function name: Set_CAR
** Descriptions: 设置RTC的CAR寄存器
** input parameters: int32_t a,int32_t b,int32_t c,int32_t d,int32_t e,int32_t f
** output parameters: none
** Returned value: none
*************************************************************************************/
void Set_CAR (int32_t a,int32_t b,int32_t c,int32_t d,int32_t e,int32_t f)
{
outpw(&RTC->CAR, a<<20|b<<16|c<<12|d<<8|e<<4|f) ;
}
/*************************************************************************************
** Function name: delay_ms
** Descriptions: 1ms(晶振为12MHZ)延时子程序
** input parameters: count
** output parameters: 无
** Returned value: 无
*************************************************************************************/
void delay_ms(uint32_t count)
{
uint32_t i,j;
for(i=count;i>0;i--)
for(j=2395;j>0;j--);
}
其他的就不传了
下面传两张图片



工程 LI-RTC-1.rar (1.69 MB)

注意:工程与半主机的略不同 就是 retarget.c函数
对了 如果校准完时间想要下次启动时为校准时间 只需将存放校准时间的数组更新一下即可

相关帖子

沙发
Swallow_0322| | 2011-9-27 11:19 | 只看该作者
沙发!
已下班,走人......

使用特权

评论回复
板凳
hotpower| | 2011-9-27 11:36 | 只看该作者
很好!
俺在定助学板的通用串口协议。

使用特权

评论回复
地板
plc_avr| | 2011-9-27 12:51 | 只看该作者
这个不错,顶!
哈哈,终于看到有人用和我一样的上位机串口调试软件了。我现在串口软件一堆,这个倒没怎么用了。

使用特权

评论回复
5
hotpower| | 2011-9-27 13:01 | 只看该作者
哈哈,俺一般都是自己做

使用特权

评论回复
6
lixiaoxu2meng|  楼主 | 2011-9-27 13:06 | 只看该作者
4# plc_avr

呵呵 我感觉这个比较好用 呵呵

使用特权

评论回复
7
lixiaoxu2meng|  楼主 | 2011-9-27 13:07 | 只看该作者
5# hotpower
老师狠人 向老师的方向努力

使用特权

评论回复
8
hotpower| | 2011-9-27 13:52 | 只看该作者
这个软件界面不错,不过没有DTR和RTS的控制。

使用特权

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

本版积分规则

0

主题

1679

帖子

2

粉丝