搜索
bottom↓
回复: 8

马老师,请教一个问题

[复制链接]

出0入0汤圆

发表于 2008-4-23 09:06:40 | 显示全部楼层 |阅读模式
程序可以正常运行,但就是感觉写的不好,希望高手指点一下
我用了两个定时器,一个是用来扫描按键,一个用来数码管计数用的.
下载以后程序可以运行(下载线还在下载端口上,没BA出来)然后关了电源,重启一下,那个PINC4接的按键就不行了,还有如果把下载线BA了,数码管就会自动计数,不知什么原因,还请马老师指点一下哦,还有就是我的数码管是1秒自动计数的,感觉要小于一秒,不知是怎么回事呀
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.7a Evaluation
Automatic Program Generator
?Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :  
Version :  
Date    : 2008-3-30
Author  : Freeware, for evaluation and non-commercial use only
Company :
Comments:  
PC4为按键计数键,按键时数码管自动加1,PC6为开始作减法自动计数键(按一下,开始减法计数,在按一下暂停,在按一下复位)

Chip type           : ATmega16
Program type        : Application
Clock frequency     : 4.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

#include <mega16.h>
flash unsigned char table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//定义字符表
flash unsigned char position[4]={0x01,0x02,0x4,0x08};
unsigned char  time[2];//显示时,分
unsigned char        led[4];        //                        
unsigned char keycnt;    //按键计数变量
unsigned int time_counter; // 中断次数计数单元
unsigned char        posit,n;
bit        point_on, time_1s_ok;   




void time_to_disbuffer(void)//显示缓冲区
{   led[0]=time[0]%10;
    led[1]=time[0]/10;
    led[2]=time[1]%10;
    led[3]=time[1]/10;  
     
}
void display(void)//数码管显示程序
{       PORTC =0X70;
        PORTD = table[led[posit]];
        PORTC= position[posit];
        if (++posit >=4 ) posit = 0;
         
}  
void delay(unsigned int a)
{
        while(a--)
         {  
         
         }  
}  

void key_in(void)//按键扫描程序
{  
if((PINC&(1<<4))==0)//按键是否按下,
     {
      delay(35000);//延时消抖?
      if((PINC&(1<<4))==0)//确认按键按下
       { time[0]++;
             if(time[0]==100)
                    {time[0]=0;}
                time_to_disbuffer();
                 
                }
          }
   
     
  
}
interrupt [TIM2_COMP] void timer2_comp_isr(void)   //Timer 2比较匹配中断服务
{                       // 调用LED扫描显示
        if (++time_counter>=500) //1秒
        {       time_1s_ok=1;
                time_counter = 0;  
                if(time_1s_ok)
                {time_1s_ok=0;
                  time[0]--;
                    n=time[0];
                  if(time[0]==0)
                  {time[0]=0;
                  
                    TIMSK=0X02;}
                  time_to_disbuffer();  
                  }
                 
        }
}
// Timer 0 比较匹配中断服务
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{      
        display();  
                                        // 调用LED扫描显示
         
}


void main(void)
{      
        PORTD=0XFF;
        DDRD=0XFF;
        PORTC=0X70;
        DDRC=0X8F;
        // T/C0 初始化
        TCCR0=0x0B;                                // 内部时钟,64分频(4M/64=62.5KHz),CTC模式
        OCR0=0x7C;                         // OCR0 = 0x7C(124),(124+1)/62.5=2ms
        TCNT0=0x00;
        TIMSK=0x02;                                // 允许T/C0比较匹配中断   
         
         
         
       time[1] = 00; time[0] = 00;                // 设初值
        posit = 0;
         
          time_to_disbuffer();
          #asm("sei");
          while(1){  
                  if((PINC&(1<<6))==0)
                   {delay(30000);
                      if((PINC&(1<<6))==0)
                       {   keycnt++;
                           switch(keycnt)
                             {
                               case 1:
                              
                                if(time[0]==0)
                                  {keycnt=0;
                                  break;}
                                TCCR2=0x0B;                                // 内部时钟,64分频(4M/64=62.5KHz),CTC模式
                                OCR2=0x7C;                         // OCR0 = 0x7C(124),(124+1)/62.5=2ms
                                TCNT2=0x00;
                                TIMSK=0x82;                                // 允许T/C2比较匹配中断  
                                
                               break;
                                 
                                   
                              
                               case 2:
                               TIMSK=0X02;//不允许T/C2比较匹配中断  
                              
                               time_to_disbuffer();
                                
                               break;
                               case 3:
                               keycnt=0;
                                 
                               time[0] = 0;
                               time_to_disbuffer();
                               break;   
                                }
                                while((PINC&(1<<6))==0);
                             }
                            } key_in();
                         }  
                        }  
                          
 

出0入0汤圆

发表于 2008-4-23 09:36:08 | 显示全部楼层
建议你下载我电子书的前2篇学习一下,编程的思想方法要更新.

出0入0汤圆

 楼主| 发表于 2008-4-23 11:58:42 | 显示全部楼层
是不是你出的那本书的前两章呀,那本书我买了

出0入0汤圆

发表于 2008-4-23 13:45:08 | 显示全部楼层
用马老师新出的书,里面有个状态机的键盘设计,用状态机的思想可以只用一个定时器实现很多功能:比如键盘单按键/按键连_发,数码管的显示,定时,PWM等等,当然功能都是在主程序里实现的,呵呵,提个方法,具体的自己琢磨一下...

出0入0汤圆

发表于 2008-4-23 17:45:54 | 显示全部楼层
1.首先在你的程序中使用delay()函数,这是我不提倡的(几个us的除外),我书中在第8章后就不使用软件延时了.
2."我用了两个定时器,一个是用来扫描按键,一个用来数码管计数用的".实际使用一个就可以了,看我书中例子.
3."数码管是1秒自动计数的,感觉要小于一秒",要准的话,最好采用外部晶体.CTC方式(这个你用对了)
4.程序冗余,乱.比如:
interrupt [TIM2_COMP] void timer2_comp_isr(void)   //Timer 2比较匹配中断服务  
{                       // 调用LED扫描显示  
   if (++time_counter>=500) //1秒
   {
       time_1s_ok=1;  
       time_counter = 0;   
       if(time_1s_ok)                    //这个判断明显多余的!!  
       {
           time_1s_ok=0;  
           time[0]--;  
           n=time[0];  
           if(time[0]==0)  
           {
               time[0]=0;  
               TIMSK=0X02;              // 这句的作用是什么?有必要吗?
           }  
           time_to_disbuffer();   
       }  
   }  
}  

5.不知道你使用哪片AVR.如果是M16,并使用ISP通过SPI下载的话,是不会影响PORTC口工作的.

===============================
你可能学过或使用过51,但建议你仔细读我的书,并体会里面的东西,会更上一层楼的.

出0入0汤圆

 楼主| 发表于 2008-4-24 09:18:16 | 显示全部楼层
马老师,非常感谢你给我的指导,这几天一直在看你的书,我想问一下,就是想学一下LCD的用法,是否可以先学你书中的那个LCD呀,那以后用到别的LCD是否会用,还是要看LCD的说明书呀
对了TIMSK=0X02; 我是想禁止定时器2产生中断,不知这样合不合适呀,我是想计数减到0时就停止,不让它继续下去了,不知还有没有好的方法呀,再次感谢!!

出0入0汤圆

 楼主| 发表于 2008-4-24 09:21:24 | 显示全部楼层
对了,还有一点,如果我只使用一个定时器的话,那我在数码管计数到0时,想不让计数了,那怎么办呀,如果把中断屏蔽掉的话,扫描程序不也就退出了,谢谢!!

出0入0汤圆

发表于 2008-4-24 11:17:02 | 显示全部楼层
STEP BY STEP 是最好的学习方法和态度.

出0入0汤圆

发表于 2011-1-6 19:54:18 | 显示全部楼层
不错,保留
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-19 09:14

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表