huxunying 发表于 2010-12-28 11:29:33

attiny13做的手电仿真可以实现,焊接实物后按键换挡没有作用。

先上电路图:
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_607597CFFLLR.png
(原文件名:SD.png)
程序如下:
/*****************
接线说明:        PB0: PWM输出, 控制模式
                                 PB1: (档位切换)按键输入检测, 平时为高电平, 有按键时变为低电平
熔丝位设置 :
                         1: SPIEN = 0        SPI下载使能
                         2: EESAVE = 1 芯片擦除时EEPROM擦除
                         3: WDTON = 1 开门狗禁用
                         4: CKDIV8 = 0 时钟不8分频
                         5: SUT1:0 = 00        快速上电
                         6: CKSEL1:0 = 10 使用内部9.6MHZ频率
                         7: SELFPRGEN = 0
                         8: DWEN = 0
                         9: BODLEVEL1:0= 10 BOD触发电平1.8V
                         10: RSTDISBL = 0;        外部复位禁用
*****************/
#include <inavr.h>
#include <iotiny13.h>

volatile unsigned int flash_sign = 0x00;
volatile unsigned int key_pattern = 0x00;
volatile unsigned int sos_count1 = 0x00;
volatile unsigned int sos_count2 = 0x00;

/****************
功能与切换状态的设置
****************/
#define        Dis_Min                1        //低亮10%
#define        Dis_Mid                2        //中亮30%
#define        Dis_Max                3        //高亮100%
#define        Dis_Flash        4        //暴闪
#define        Dis_Sos                5       
//SOS求救信号(3短3长3短)
//长的时间是三个短的时间
//短和短,长和长之间的间隔为一个短的时间
//短和长之间的间隔是三个短的时间
//两次发送间隔是7个短的时间
#define        Dis_top                5        //支持模式最大值

/****************
占空比设置
****************/
#define Stack_min0xe0
#define Stack_mid0xa0
#define Stack_max0x01
#define Stack_flash0xd0
#define Stack_sos 0xb0

/***************
Use_eeprom=1 亮度记忆功能
Use_eeprom=0 没有亮度记忆功能
***************/
#define Use_eeprom        0

/****************
PB0为PWM模式输出;
PB1为按键信号检测,控制模式切换
****************/
void IO_init(void)
{
        DDRB = 0x1d; //0001 1101
        PORTB = 0x02;//0000 0010
}
void Inter_pwm(void)
{
        TCCR0B = 0x00;        //关T/C0
        PORTB &= 0xfe;
        TCNT0 = 0x00;        //设置TC0计数寄存器初值
        TCCR0A = 0xc3;        //比较匹配时set OC0A;TOP时clr OC0A
        TIMSK0 &= 0xf1;        //屏蔽OCIE0A与TOIE0中断
        TCCR0B = 0x01;        //开T/C0;开T/C0;不预分频      
}
void Inter_ctc(void)
{
        TCCR0B = 0x00;        //关T/C0
        PORTB &= 0xfe;
        TCNT0 = 0x00;        //设置TC0计数寄存器初值
        TCCR0A = 0x02;        //CTC模式
        TIMSK0 |= 0x0f;        //输出比较匹配OCIE0A 中断使能
        SREG |= 0x80;        //开启全局中断I
        TCCR0B = 0x05;        //开T/C0;1024分频
}
void Display_status(unsigned int Dis_st)
{
      if(Dis_st == Dis_Flash)
             flash_sign = 0x01;
      else
         flash_sign = 0x00;
        switch(Dis_st)
                {
                        case Dis_Min:                OCR0A = Stack_min;
                                                        Inter_pwm();
                                                       break;
                        case Dis_Mid:         OCR0A = Stack_mid;
                                                        Inter_pwm();
                                                       break;
                        case Dis_Max:         OCR0A = Stack_max;
                                                        Inter_pwm();
                                                       break;
                        case Dis_Flash:         OCR0A = Stack_flash;
                                                        Inter_ctc();
                                                        break;
                        case Dis_Sos:                OCR0A = Stack_sos;
                                                        sos_count1 = 0x00;
                                                        sos_count2 = 0x00;
                                                        Inter_ctc();
                                                    break;
                }
}
#if Use_eeprom
#define ER_address 0x00//设置数据在EEPROM中存储地址
void EEPROM_write(unsigned char Address, unsigned char Data)
{
       SREG &= 0x7f;        //关全局中断;防止写操作有中断产生
        while(EECR & 0x02);         //等待上一次写操作结束
        EECR &= 0x0f;         //设置编程模式
        EEAR = Address;
        EEDR = Data;        //设置地址与数据寄存器
        EECR |= 0x04;
        EECR |= 0x02;         //启动写操作
       SREG |= 0x80;   //开全局中断
}
void EEPROM_read(unsigned char Address)
{
        while(EECR & 0x02);       //等待上一次写操作结束
        EEAR = Address;
        EECR |= 0x01;        //启动读操作
       key_pattern = EECR;
        Display_status(key_pattern);       
}
#endif
void Key_check(void)
{
        static unsigned int key_sign = 0x00;
        static unsigned int i = 0x00;
#if        Use_eeprom
        static unsigned int j = 0x00;
        if(key_sign==0x01)
                {
                        if(++j>100)
                                {
                                        EEPROM_write(ER_address, key_pattern);
                                        j = 0x00;
                                }
                }
#endif
        if((PINB&0x02)==0x00)
                {
                        i++;
                        if(i>200)
                                key_sign = 0x01;
                }
        if(key_sign == 0x01)
                {
                        i = 0x00;
                        if((PINB&0x02)==0x02)
                                {
                                        PORTB ^= 0x04;        //test
                                        if((++key_pattern)>Dis_top)
                                                        key_pattern= 0x01;
                                 Display_status(key_pattern);
                                        key_sign = 0x00;                                       
                                }
                }               
}
#pragmavector = TIM0_COMPA_vect
__interrupt void CTC_COMPA(void)
{
        TIFR0 &= 0xfa;        //清除 OCF0A输出比较标志位
       if((TCCR0A & 0x02) == 0x02)       
               {
                       if(flash_sign == 0x01)
                                PORTB ^= 0x01;
                        else
                                {       
                                        if(sos_count1 > 0)
                                                sos_count1--;
                                        else
                                                {
                                                        PORTB ^= 0x01;
                                                          switch(++sos_count2)
                                                                {
                                                                        case 0x06:        sos_count1 = 0x02;
                                                                                break;
                                                                        case 0x07:        sos_count1 = 0x02;
                                                                                break;
                                                                        case 0x09:        sos_count1 = 0x02;
                                                                                break;
                                                                        case 0x0b:        sos_count1 = 0x02;
                                                                                break;
                                                                        case 0x0c:         sos_count1 = 0x02;
                                                                                break;
                                                                        case 0x12:         sos_count1 = 0x06;
                                                                                                sos_count2 = 0x00;
                                                                                                return;
                                                              }                                                                                               
                                                }                       
                                }
                  }
}
void main(void)
{
        IO_init();
#if        Use_eeprom
        EEPROM_read(ER_address);
#else
        key_pattern = Dis_Sos;
        Display_status(key_pattern);
#endif      
        while(1)
                {
                        Key_check();
                }
}
这个程序用POTUES仿真可以,但是我用实物仿真的时候开关电后档位不会发生变化;即使我把PB1口设置为按键输入直接拉低 档位也不会变化。。。。小弟第一次学写程序 希望各位前辈指点指点 。。。。先在此谢谢过。。。

machao 发表于 2010-12-30 20:53:05

听我的建议,对于初学者,不要使用什么“仿真”,从简单的DD开始,实物练习。

等你具备了一定的水平和能力后,才知道如何真正使用仿真。

一根接线接错了,二极管装反了,溶丝位设置不对,这个你能“仿真”出来吗?这种查错的能力不是仿出来的,只能在实际的做中得到锻炼和经验。

Cliff 发表于 2010-12-31 09:24:09

1楼说的很对啊!

看了楼主(代表了当前大部分的“好学生”,因为“坏学生”们都去“不务正业”了)的描述,我也很感慨的:
这也是我们教育的问题,很严重的问题:理论和实践的严重脱节!

我想对楼主说,你到大学学习,更重要的是要学会分析问题和解决问题的能力,可很遗憾,在你的言论中我看得出,你还不具备。

例如,上述的电路,其实可以分成两个相互独立的单元,分别进行调试的。一块是LED驱动,一块是PWM。可是你却只是抛出一整个大问题,全部的电路,加上全部的程序,丢给大家来解决,这怎么行呢?

然后,就是仿真。仿真只是验证你设计阶段的想法的一个手段。特别是在试制成本非常高的时候(比如IC设计),这是有用的手段。但是,并非仿真就一定等于实际。有时候仿真过了,实际的通不过;甚至会发生仿真通不过而实际可用的情况。

最后我要感慨一下不少人对“科学”二字的认识。比如前段时间的中_医(伪)科学之争。我看倒一个能左右大众思想言论的学者,竟然抛出这样的话语,很是伤心!
什么是科学?能验证的是科学吗?“中”医是不能用现阶段的科学理论来验证的,那它就是不科学的,就该废除吗?
恰恰相反,科学是探索,是发现,是否定,是证伪。

huxunying 发表于 2010-12-31 17:52:50

十分感谢 machao 和 Cliff 的建议和指点。。。程序中问题已经解决, 同时验证了仿真有时候不一定可靠。

cuikai12345 发表于 2010-12-31 20:59:00

mark

668880 发表于 2011-4-15 16:15:05

我也在学习






请问最后问题在那!谢谢!

kmcool 发表于 2011-4-15 16:35:34

LZ不就问个小问题。。。。真能扯。。。
页: [1]
查看完整版本: attiny13做的手电仿真可以实现,焊接实物后按键换挡没有作用。