正文

DIY旋转时钟2011-12-02 23:36:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/enc999/53041.html

分享到:

/-------------------------------------------------------- // 项目:梦幻旋转时钟 // 模块:主程序 // 说明: // 设计:程序匠人(版权所有,引用者请保留原作者姓名) //-------------------------------------------------------- /* 版本说明: v01 2008-1-6 0:26  第一个程序   v02 2008-1-6 0:26  1.LED驱动改为负极控制  2.缺省时间改为1:15分  3.修改显示部分   v03 2008-1-6 1:59  1.时针定位原先的算法有误,修改之  2.该进显示内容,3.6.9.12直接显示数字v04 2008-1-8 23:05  1.优化部分程序的写法  2.扩展部分程序 v05 2008-1-9 21:25  1.TMR0中断赋初值部分程序有误,导致计时误差(1分钟慢10秒左右).修改之   原来:  TMR0 = 256-(250-2) ;    //TMR0赋初值   改为:  TMR0 = TMR0 + (256-(250-2)) ;   //TMR0赋初值 v06 2008-1-14 23:37  1.显示程序,增加一种数字表盘模式  2.其它改进 v07 2008-1-16 22:07  1.数字表盘模式,增加钟摆效果  2.加大"调整单列显示时间设置值(模糊控制)"的速度 v08 2008-1-17 22:09  1.收缩钟摆的摆动幅度  2.中断查询中,先判触发标志,后判使能标志.(可以提高响应速度)  3.添加串行接收功能(波特率=2400)(通讯已经测试成功!)   A.初始化部分   B.中断部分   C.串行通讯后台处理部分  4.实现角度校准功能 v09 2008-1-23 22:42  1.完成全部显示控制程序  2.波特率改为1200,增强通讯可靠性 v10 2008-1-26 15:17  1.增加ADC程序模块  2.增加温度检测及显示程序  3.增加滤波程序(中位值递推平均滤波) v11 2008-2-10 16:46  1.将单文件系统改为多文件系统.原来只有一个 "clock.c"文件,现在拆分为以下若干个程序文件和头文件模块:   main.c  //主程序 程序文件   display.c //显示处理 程序文件   filter.c  //滤波处理 程序文件   temperature.c  //温度处理 程序文件   Serial.c //串行通讯 程序文件   Interruption.c //中断服务 程序文件   common.h //公共 头文件   main.h  //主程序 头文件   display.h //显示处理 头文件   filter.h  //滤波处理 头文件   temperature.h  //温度处理 头文件   Serial.h //串行通讯 头文件   Interruption.h //中断服务 头文件 v12 2008-2-10 23:01  1.增加内部eeprom与FLASH操作模块(将角度校正值和闹钟参数保存在内部EEPROM中)  2.增加一个无按键计数器,当一定时间内未接收到新的命令时,退出设置状态,并把参数保存到内部EEPROM中  3.改进秒闪功能.在按键2秒内,被设置参数不闪烁.  4.修改配置位内容  5.闹钟模式增加进度条  6.细节改动   */ //-------------------------------------------------------- //-------------------------------------------------------- //插入文件包 //-------------------------------------------------------- #define root #include "common.h" //--------------------------------------------------------   //-------------------------------------------------------- //定义芯片工作时的配置位 //-------------------------------------------------------- __CONFIG(HS & WDTDIS & PWRTDIS & BOREN & LVPDIS & DUNPROT & WRTEN & DEBUGDIS & UNPROTECT); //__CONFIG(HS & WDTDIS  & LVPDIS ); //-------------------------------------------------------- //主函数 //-------------------------------------------------------- void main(void) {  init();      //====初始化  //====循环主体  while (1)  {   asm ("clrwdt");     //喂狗   //asm ("nop");       //   if ( T_10MS_FLAG ) time_cnt() ;    //如果10毫秒定时溢出标志=1,则调用计时处理程序   if ( NEW_DISP_EN_FLAG ) new_display() ;   //如果显示刷新使能标志=1,则刷新显示缓冲区     if ( ADGO == 0 ) adc_cnt() ;    //如果ADC结束,则调用ADC处理程序   if ( TEMP_SCAN_EN_FLAG ) temp_cnt() ;     //如果温度检测使能标志=1,则调用温度处理程序      comm_cnt();      //串行通讯后台处理      if ( (EEPROM_NEW_FLAGS!=0) && (WR==0) && (NO_KEY_JSQ>5) ) new_eeprom() ; //如果EEPROM数据更新标志<>0,且写操作结束,且无按键计数器>5,则更新eeprom内容  } }   //-------------------------------------------------------- //初始化程序 //-------------------------------------------------------- void init(void) {  //====IO口设置  PORTA = 0B00111100 ;  //设置PORTA口电平  TRISA = 0B00000001 ;  //设置PORTA口输入/输出态  PORTB = 0B11111110 ;  //设置PORTB口电平  TRISB = 0B00000001 ;  //设置PORTB口输入/输出态  PORTC = 0B00001011 ;  //设置PORTC口电平  TRISC = 0B10000000 ;  //设置PORTC口输入/输出态  (串行接收口RX(RC7)设置为输入态)  //====寄存器初始化  //====参数初始化  DISP_TIME_SET = (65536-1000) ; //单列显示时间设置值  DISP_LINE = DISP_LINE_ADJ ; //显示列计数器(0~179)=校正值  TIMR1_JSQ = 0 ;   //TIMR1溢出计数器 = 0  MOTOR_ST_FLAG = 1 ;  //电机状态标志=1(0=关闭,1=开启)  SET_EN_FLAG = 0 ;  //设置使能标志=0(0=禁止,1=使能)  DISP_MODE = 0 ;   //显示状态(0~7)  SET_MODE = 0 ;    //设置状态(0~7)  TIME_H = 12 ;                  //时钟"时"(0~23)  TIME_M  = 0 ;                  //时钟"分"(0~59)  TIME_S  = 0 ;                   //时钟"秒"(0~59)  TIME_MS = 0 ;                   //时钟"毫秒"(0~99) (每过10ms,+1)  TIME_US = 0 ;                   //时钟"微秒"(0~179) (每过(250*0.222us)=55.556us,+1)  T_10MS_FLAG = 0 ;  //10毫秒定时溢出标志(0=未溢出,1=溢出)  NEW_DISP_EN_FLAG = 1 ;  //显示刷新使能标志=1(0=禁止,1=使能)  COMM_PUT_PTR = 0 ;       //接收数据存放指针=0  COMM_GET_PTR = 0 ;  //接收数据读取指针=0  SP_RUN = 0 ;   //闹铃时间运行值(0~99分)  NO_KEY_JSQ = 0 ;   //无按键计数器=0(每1S+1)  //温度历史纪录队列  TEMP_LS_QUEUE[0]=25 ;  TEMP_LS_QUEUE[1]=25 ;  TEMP_LS_QUEUE[2]=25 ;  TEMP_LS_QUEUE[3]=25 ;  TEMP_LS_QUEUE[4]=25 ;  TEMP_LS_QUEUE[5]=25 ;  TEMP_LS_QUEUE[6]=25 ;  TEMP_LS_QUEUE[7]=25 ;  TEMP_LS_QUEUE[8]=25 ;  TEMP_LS_QUEUE[9]=25 ;  TEMP_LS_QUEUE[10]=25 ;  TEMP_LS_QUEUE[11]=25 ;  TEMP_LS_QUEUE[12]=25 ;  TEMP_LS_QUEUE[13]=25 ;  TEMP_LS_QUEUE[14]=25 ;  TEMP_LS_QUEUE[15]=25 ;  TEMP_LS_QUEUE[16]=25 ;  TEMP_LS_QUEUE[17]=25 ;  TEMP_LS_QUEUE[18]=25 ;  TEMP_LS_QUEUE[19]=25 ;  TEMP_LS_QUEUE[20]=25 ;  TEMP_LS_QUEUE[21]=25 ;  TEMP_LS_QUEUE[22]=25 ;  TEMP_LS_QUEUE[23]=25 ;  TEMP_LSPJ=25 ;  //====EEPROM中参数初始化  eeprom_init() ;    //====INT口,WDT,TIMR0设置  OPTION = 0B10001111 ;  //预分频器分配给WDT; 预分频=1:128; TMR0时钟源=内部指令周期计数; PORT内部上拉禁止; NT口触发边沿=下降沿;  TMR0 = 256-250 ;  //TMR0赋初值  //====TIMR1设置  T1CON = 0 ;   //TMR1控制寄存器=0  TMR1HL = DISP_TIME_SET ; //TMR1赋初值  T1CKPS1 = 0 ;  T1CKPS0 = 0 ;   //预分频系数=1:1  T1OSCEN = 0 ;   //关闭内部振荡器电路  T1SYNC = 0 ;   //同步计数模式  TMR1CS = 0 ;   //时钟源=内部指令周期计数  TMR1ON = 1 ;   //计数使能    //====串口设置(说明:只接收,不发送,半工异步通讯,波特率=1200,数据位=8bit,停止位=1bit,无校验位)  SPBRG = 233 ;   //波特率=fosc/64(SPBRG+1)=18000000/(64*(233+1))=1201.92    TXSTA = 0B00000000 ;  //异步低速方式,发送8bit数据  RCSTA = 0B10010000 ;  //串口工作使能,接收8bit数据,连续接收允许    //====ADC设置  ADCON1 = 0B00001110 ;  //选择AN0通道为模拟口,其它通道为数字口  ADCON0 = 0B11000001 ;  //ADC时钟源=自带RC;通道选择AN0;启动AD模块电源  ADGO = 1 ;   //启动ADC  //====中断使能  INTCON = 0 ;   //中断控制寄存器=0  PIE1 = 0 ;  PIE2 = 0 ;  INTE = 1 ;    //使能INT中断  T0IE = 1 ;   //TMR0中断  TMR1IE = 1 ;   //TMR1中断  TXIE = 0 ;   //串口发送中断  RCIE = 1 ;   //串口接收中断    PEIE = 1 ;   //外设中断  GIE = 1 ;   //全局中断   } //-------------------------------------------------------- //EEPROM中参数初始化程序 //-------------------------------------------------------- void eeprom_init(void) {  EEADR = EEPROM_EN_ADR ;     read_eeprom() ;    //读取 EEPROM格式化标志    if ( EEDATA == 0XA5 )  {   EEADR = DISP_LINE_ADJ_ADR ;      read_eeprom() ;   //读取 显示列计数器 角度校正值(0~179) (用于校正盘面角度)   DISP_LINE_ADJ = EEDATA ;      EEADR = TIMER_H_ADR ;      read_eeprom() ;   //读取 闹钟"时"(0~23)   TIMER_H = EEDATA ;   EEADR = TIMER_M_ADR ;      read_eeprom() ;   //读取 闹钟"分"(0~59)   TIMER_M = EEDATA ;   EEADR = SP_M_ADR ;      read_eeprom() ;   //读取 闹铃时间设置值(0~99分)(说明:0=关闭闹钟)   SP_M = EEDATA ;  }  else  {   DISP_LINE_ADJ = 0 ;  //显示列计数器 角度校正值(0~179) (用于校正盘面角度)     //闹钟系统   TIMER_H = 7 ;   //闹钟"时"(0~23)   TIMER_M = 15 ;   //闹钟"分"(0~59)   SP_M = 1 ;   //闹铃时间设置值(0~99分)(说明:0=关闭闹钟)   //EEPROM数据更新标志=1   DISP_LINE_ADJ_FLAG = 1 ; //显示列计数器 角度校正值(0~179) (用于校正盘面角度)          TIMER_H_FLAG = 1 ;  //闹钟"时"(0~23)                                             TIMER_M_FLAG = 1 ;  //闹钟"分"(0~59)                                             SP_M_FLAG = 1 ;   //闹铃时间设置值(0~99分)(说明:0=关闭闹钟)                    EEPROM_EN_FLAG = 1 ;  //EEPROM格式化标志(0XA5=已经格式化,否则=未格式化)           } } //-------------------------------------------------------- //计时处理程序 //功能: 1.计时 // 2.电机停转判断 //-------------------------------------------------------- void time_cnt(void) {  tU08 i,j ;  T_10MS_FLAG = 0 ;    //10毫秒定时溢出标志=0  NEW_DISP_EN_FLAG = 1 ;    //显示刷新使能标志=1(0=禁止,1=使能)  TEMP_SCAN_EN_FLAG = 1 ;    //温度检测使能标志=1(0=禁止,1=使能)  //====计时  if ( ++TIME_MS > 99 )     //"毫秒"+1,结果>最大值?  {   TIME_MS = 0 ;    //"毫秒"=0   if ( ++TIME_S > 59 )    //"秒"+1,结果>最大值?   {    TIME_S = 0 ;    //"秒"=0    if ( ++TIME_M > 59 )    //"分"+1,结果>最大值?    {     TIME_M = 0 ;    //"分"=0     if ( ++TIME_H > 23 ) TIME_H = 0 ; //"时"+1,结果>最大值时,=0     TEMP_LS_NEW_FLAG = 1 ;          //温度历史纪录队列更新使能标志=1(0=禁止,1=使能)    }   }      //====电机停转判断   if ( ++MOTOR_STOP_JSQ > 3 )             //电机停转计时器+1,>3?   {    MOTOR_ST_FLAG = 0 ;  //电机状态标志=0(0=关闭,1=开启)    SET_EN_FLAG = 0 ;  //设置使能标志=0(0=禁止,1=使能)   }   //====无按键计数器+1   if ( ++NO_KEY_JSQ > 250 ) NO_KEY_JSQ = 250 ;   //无按键计数器+1,>250时,=250   if ( NO_KEY_JSQ > 15 ) SET_EN_FLAG = 0 ;  //如果无按键计数器>15,则设置使能标志=0(0=禁止,1=使能)  }    //====设置秒闪标志(1HZ)  if ( TIME_MS > 49 ) MS_1HZ_FLAG = 1;  else MS_1HZ_FLAG = 0 ; } //-------------------------------------------------------- //ADC处理 //出口: ADR_NEW=最新AD结果 //-------------------------------------------------------- void adc_cnt(void) {  ADR_NEW = ADRESH ;     //保存最新AD结果  ADGO = 1 ;      //重新启动ADC } //-------------------------------------------------------- // // THE END // // 版权所有:程序匠人(引用者请保留原作者姓名) // //--------------------------------------------------------

阅读(1910) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册