《匠人手记》推荐网上购书渠道:
互动出版网(china-pub)购书入口   >>>
当当网(dangdang)购书入口   >>>
卓越亚马逊网 购书入口   >>>
淘宝网(taobao)购书入口   >>>
更多购书渠道……   >>> 

设为首页加入收藏联系匠人管理入口21IC首页21IC博客21IC社区侃单片机回复的贴参与的贴

天气预报
百宝日历
载入中...

百宝专栏

载入中...
最新货色

载入中...

粉丝评论

载入中...

载入中...



百宝信息

载入中...

百宝流量

(2006-07-01开始)


匠人手记

 匠人观点: 好记性不如烂笔头  
 黑色幽默:三鹿门——后世畅想

匠人DIY旋转时钟全程实播(连载19:主函数源程序)
程序匠人 发表于 2008-3-5 22:52:00  阅读全文 | 回复(0) | 引用通告 | 编辑

相关连接: [匠人DIY旋转时钟 系列文章 (连载中…)]

//--------------------------------------------------------
// 项目:梦幻旋转时钟
// 模块:主程序
// 说明:
// 设计:程序匠人(版权所有,引用者请保留原作者姓名)
//--------------------------------------------------------
/*
版本说明:
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
#i nclude "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
//
// 版权所有:程序匠人(引用者请保留原作者姓名)
//
//--------------------------------------------------------


 

看《匠人手记》,与匠人同行!北航出版,正在热卖!

发表评论:
载入中...

芯片专题

器件专题

软件专题

硬件专题

综合专题

项目专题

原创专题

器件检测
LCD LED
按键 触摸键
E2PROM
电池 电机
电阻 电容 电感

指令系统
软件算法
编程规范
滤波算法
串行通讯

PCB设计
I2C PWM
红外遥控
充电技术
中断 ADC 

匠人手记
匠人夜话
网络心路
一周热点串烧
从零开始玩PIC
DIY旋转时钟

广告5号位 [投放]


学习板、开发板、编程器、下载器、仿真器(查看详情……)

广告3号位 [投放]

站内搜索


站外搜索


百度  google
mp3  歌词 
图片  FLASH 
知道  文档
新闻  词典 
地图  mp3 
软件  天网 
雅虎  爱问 
搜狗  讯雷 
网讯  华军 
天空 

21IC器件搜索
百宝箱分站
  • 《匠人的百宝箱》21IC站
  • 《匠人的百宝箱》21IC笔记团队
  • 《匠人手记》21IC书友会
  • 《匠人的百宝箱》MCUBLOG站
  • 《匠人的百宝箱》MCUBLOG笔记团队
  • 《匠人的百宝箱》EDN站
  • 《匠人手记》EDN书友会
  • 《匠人的百宝箱》与非网站
  • 《匠人的百宝箱》新浪站
  • 《匠人的百宝箱》百度站
  • 《匠人的百宝箱》网易126站
  • 《匠人的百宝箱》网易163站
  • 《匠人的百宝箱》互动出版网站
  • 广告4号位 [投放]

     
     

    匠人原创

    往日酷贴

     
     
     

    大千八卦

    友情连接

    新浪新闻:
    新浪财经:
    AK58新闻:
    新浪股票:
    新浪股票:
    证券之星:

     [更多酷站连接]

     

     

    [欢迎交换连接]

    [百宝箱之与非门分舵]

    [电脑圈圈的家当]

    [IC921的博客]

    [柔月阁]

    [八楼的呼吸]

    [hotpower 的水潭]

    [xwj的文君阁]

    [所长的BLOG]

    [阿摆手记]

    [电子伙伴]

    [unaided的笔记]

    [小飞的笔记]

    [单片机开发联盟]

    [网址之家]

    [好东西网址大全]

    [美萍中文精选]

    [数字电视之家]

    [SMARTCODE电子书斋]

    [软件开发之窗]

    [Armoric]

    [我爱研发网]

    [infernal的笔记]

    [雄鹰的空中加油站]

    [SunK]

    [逍遥电子]

    [ningpanda的博客]

    [C-Design]

    [一网见天下]

    [海边淘沙]

    [嵌入式365]

    [水牛的仓库]

    [股剩是怎样炼成的]

    [PIC论坛]

    [ICC AVR开发网]

    [中国高校自动化网]

     

     

     

    MCU博客-中国电子工程师博客网 

    大学生电子网 

     

     

     

     

     

    !!! 《匠人的百宝箱》 !!!