southtiger 发表于 2008-3-6 16:19:20

请马潮老师再次帮忙解答mega48的T/C1执行CTC动作的问题

程序如下:
       ; CPU: MEGA48

.equ    fosc      = 8                     ; FOSC=8.0 MHz
.equ    t1_all    = 125000                  ; T1定时的总时间(us)
.equ    t1_940us= 940                     ; time for pre_Vpp
.equ    t1_20us   = 20                      ; time for emitting
.equ    t1_120us= 120                     ; time for after_Vpp
.equ    t1_end    = (t1_all-t1_940us-t1_20us-t1_120us)*fosc
.equ    t1_940init= t1_940us*8+16
.equ    t1_20init = t1_20us*8-4
.equ    t1_120init= t1_120us*8-3
.equ    t1_status = 0x0100                  ; t1定时的状态
.equ    t1_count= 0X0101                  ; t1定时5ms的次数
.equ    timer1_cnt=25                         ; 定时1s的次数
.equ    t1_125init= t1_all/timer1_cnt*8-2   ; 初始值

;.def    timer1_count=R19

.INCLUDE "m48def.inc"

       .ORG   $000         ;精确定时产生秒号
STRT25: RJMP    RST25   
   
       .ORG   $00b         ;T1 Capture
      RJMP    T1_OVFB      ;4000133=62*65536-63099=62*$10000-$F67B/故TCC=$F67B

       .ORG   $01b         
RST25:LDI   R16,HIGH(ramend)
      OUT   SPH,R16
      LDI   R16,LOW(ramend)
      OUT   SPL,R16
      RCALL   T1_initial   
      LDI   R16,0b00001001 ;不分頻
      ;STS    TCCR1A, $00    ; COM1A1/COM1A0/COM1B1/COM1B0/-/-/WGM11/WGM10 (默认值:00H)   
      STS   TCCR1B,R16   ; ICNC1/ICES1/-/WGM13/WGM12/CS12/CS11/CS10
                         ;WGM13, WGM12, WGM11, WGM10 = 0100 -> CTC模式(MAX=OCR0A)
                        CS12,CS11,CS10 = 001 -> Fosc/1 (无分频,000->T/C停止)   ;       
      SEI                  ;
HH1B:   RJMP    HH1B         ;等待中断

;************** T/C1 初始化子程序 *******************
T1_initial:      
        LDI   R16,$03      
        OUT   DDRC, R16
        LDI   R16,$00
        OUT   PORTC,R16

      LDI   R16,timer1_cnt ;62次中断定出秒号
      MOV   R6,R16
      LDI   R16,$00      ;000->T/C停止
        STS   TCCR1B,R16   ;
        LDI   R16,$02      ;
      STS   TIMSK1,R16   ;允许T/C1的A匹配中断:
      LDI   R16,$00
        STS   TCNT1H,R16
        STS   TCNT1L,R16
      LDI   R16,HIGH(t1_940init)
      STS   OCR1AH,R16   ;写入OCR1A高8位
        ;对于扩展的I/O 空间段0x60 - 0xFF 只能使用ST/STS/STD 和LD/LDS/LDD 指令。
      LDI   R16,LOW(t1_940init)      ;
      STS   OCR1AL,R16   ;写入OCR1A低8位
        LDI   R16, $10
        STS   t1_status, R16   ;T/C1的起始状态: 10
        LDI   R16,0b00000010 ;Vpp=1, Vemit=0
        OUT   PORTC,R16
      RET


;*************** 中断服务程序区 ***************************
T1_OVFB:
      LDS   R16, t1_status
      CPI   R16,   $10
      BRNE    STATUS_11
STATUS_10:
      SBI   PORTC,0            
      LDI   R16,HIGH(t1_20init)       
      STS   OCR1AH,R16            ;写入OCR1A高8位
      LDI   R16,LOW(t1_20init)      ;
      STS   OCR1AL,R16            ;写入OCR1A低8位
        LDI   R16,$11
        STS   t1_status, R16      ;T/C1新的状态:11
      RETI
STATUS_11:
      CPI   R16,   $11
        BRNE    STATUS_01
      CBI   PORTC,0            
      LDI   R16,HIGH(t1_120init)
      STS   OCR1AH,R16            ;写入OCR1A高8位
      LDI   R16,LOW(t1_120init)      ;
      STS   OCR1AL,R16            ;写入OCR1A低8位
        LDI   R16,$01
        STS   t1_status, R16      ;T/C1新的状态:01
      RETI
STATUS_01:
      CPI   R16,   $01
      BRNE    STATUS_00
      CBI   PORTC,1            
      LDI   R16,HIGH(t1_125init)
      STS   OCR1AH,R16            ;写入OCR1A高8位
      LDI   R16,LOW(t1_125init)      ;
      STS   OCR1AL,R16            ;写入OCR1A低8位
      LDI   R16,$00
      STS   t1_status, R16      ;T/C1新的状态:01
      RETI
STATUS_00:
      LDS   R16, t1_count
      INC   R16
      STS   t1_count,R16
      CPI   R16, timer1_cnt
      BRNE    STATUS_00_NOEND
      LDI   R16,   $00          ; 25*5ms = 125ms
                STS   t1_count,R16
      SBI   PORTC,   0         
      LDI   R16,HIGH(t1_940init)
      STS   OCR1AH,R16            ;写入OCR1A高8位
                LDI   R16,LOW(t1_940init)      ;
      STS   OCR1AL,R16            ;写入OCR1A低8位
      LDI   R16,$10
      STS   t1_status, R16      ;T/C1新的状态:00
      RETI
STATUS_00_NOEND:
      LDI   R16,HIGH(t1_125init)
      STS   OCR1AH,R16            ;写入OCR1A高8位
      LDI   R16,LOW(t1_125init)      ;
      STS   OCR1AL,R16            ;写入OCR1A低8位
        LDI   R16,$00
        STS   t1_status, R16      ;T/C1新的状态:00
      RETI

southtiger 发表于 2008-3-6 16:25:54

(接上)
无论软件仿真(时序为:940us->19.88/20.13us->120/120.25us->124998.37/124998.12us)
还是烧写新片后均出现类似于 19.88/20.13us->120/120.25us->124998.37/124998.12us不稳定的时序,
在此敬请马老师给予解答,谢谢!

(补充:以上时间在以下断点处测量:
STATUS_10:
      SBI   PORTC,0            
      LDI   R16,HIGH(t1_20init);断点检测

STATUS_11:
      CPI   R16,   $11
      BRNE    STATUS_01
      CBI   PORTC,0            
      LDI   R16,HIGH(t1_120init) ;断点检测

STATUS_01:
      CPI   R16,   $01
      BRNE    STATUS_00
      CBI   PORTC,1            
      LDI   R16,HIGH(t1_125init) ;断点检测

STATUS_00:
      LDS   R16, t1_count
      INC   R16
      STS   t1_count,R16
      CPI   R16, timer1_cnt
      BRNE    STATUS_00_NOEND
      LDI   R16,   $00          ; 25*5ms = 125ms
      STS   t1_count,R16
      SBI   PORTC,   0            
      LDI   R16,HIGH(t1_940init);断点检测

以上4个断点的时序检测出现变化情况,归结于定时不精确)

machao 发表于 2008-3-6 16:25:55

把项目要求和经费给我吧,很快就给你完成.

southtiger 发表于 2008-3-6 19:08:05

我是打工仔啊,别嘲笑我啦

machao 发表于 2008-3-6 21:36:06

我不是嘲笑你.

我是教师,因此希望你能真正掌握本领,把基础打好.换句话讲,是督促和希望你能掌握打鱼的本领,而不是送条鱼给你.

我已经将思路给你了,你应该通过自己的努力把它实现.如果老是要个程序,那么连打工仔也做不了.

machao 发表于 2008-3-7 02:06:34

/*****************************************************
Chip type         : ATmega48
Clock frequency   : 4.000000 MHz
Memory model      : Small
External SRAM size: 0
Data Stack size   : 128
*****************************************************/
#include <mega48.h>

#define OCR1A (*(unsigned int*)0x88) //补充定义16位寄存器OCR1A,它在mega48.h中未定义

char step;
// Timer 1 output compare A interrupt service routine
interrupt void timer1_compa_isr(void)
{
    switch (step)
    {
      case 0:
            OCR1A = 3758;
            break;
      case 1:
            OCR1A = 79;
            break;
      case 2:   
            OCR1A = 4319;
            break;
      case 3:
            OCR1A = 199;
            break;
    }      
    if (++step >= 4) step = 0;
}

void main(void)
{
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=0 State0=T
PORTB=0x00;
DDRB=0x02;          // 在PORTB.2上输出波形

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 4000.000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Toggle
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
// desired value: 940uSec
// actual value: 940.000uSec (0.0%)
TCCR1A=0x40;
TCCR1B=0x09;
OCR1AH=0x0E;
OCR1AL=0xAE;

// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x02;

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here

      };
}

==========================
试试看.

rogerllg 发表于 2012-2-1 19:33:24

回复【5楼】machao
-----------------------------------------------------------------------

DDRB=0x02;          // 在PORTB.2上输出波形

马老师,应该是PORTB.1吧! OCR1B在一些模式下不支持可调的PWM输出吧?
页: [1]
查看完整版本: 请马潮老师再次帮忙解答mega48的T/C1执行CTC动作的问题