AVR ATMEGA / ATTINY 타이머 미러링 출력 이해에 도움이 필요합니다


10

Arduino에서 사용되는 AtMega328 또는 ATTiny85 인 Atmel AVR 마이크로 컨트롤러의 Timer1을 사용하여 서로 거울상 인 두 개의 클럭 신호를 출력하려고합니다. 내가 생성하려고하는 주파수는 컨트롤러에서 거의 아무것도하지 않으려는 경우 코드를 사용하여 출력 핀을 토글하기에 너무 높은 1MHz ~ 2MHz 이상의 변수입니다. 따라서 타이머 출력을 관련 핀에서 직접 사용하고 싶습니다. arduino 라이브러리 또는 언어로 제한되지 않는 GCC 툴 체인을 사용하고 있습니다.

Atmega328의 Timer1에는 두 개의 핀이 연결되어 있으며 두 개의 동일한 1MHz ~ 2MHz 신호를 얻을 수 있습니다. 데이터 시트에 역 파형을 얻을 수 있다고 말하지만 혼란 스럽습니다. 또한 Timer1의 PWM 설정을 사용하여 1MHz에서 듀티 사이클이 다른 두 개의 신호를 얻을 수 있지만 두 신호가 동시에 높을수록 더 짧은 신호는 더 일찍 낮아집니다. 이것은 내 프로젝트를 제공하지 않습니다. PWM 펄스 폭 변화도 필요하지 않으며 반대 위상의 동일한 두 개의 "클럭"유형 신호 만 있으면됩니다.

나는 누군가 에게이 작업을 수행하기 위해 코드를 작성하도록 요구하지 않고 타이머의 모드 / 플래그가 타이머와 관련된 두 개의 핀 중 하나에서 간단한 반전 파형을 제공해야한다고 알려주는 사람이 필요합니다. 가능하다면 옵션 중 하나가 아닌 한 출력 중 하나에 외부 반전 회로를 사용하지 않으려 고합니다.

ATTiny에서 이것이 가능하다면 훨씬 더 나을 것입니다. ATTiny에는 하나의 타이머와 관련된 2 개의 핀이 있지만 ATMega와 동일한 옵션이 있는지 확실하지 않습니다.

이미 20MHz 크리스털이 있고 커패시터가 PCB에 연결되어 있고 20MHz 클럭이 ATMega328에서 안정적으로 작동하고 있습니다. ATTiny85 PCB에는 8MHz 크리스털이 있으며 안정적으로 작동합니다.

도와주세요. 감사합니다.


업데이트 : 지금까지 답변과 의견에 잘못된 가정이 있습니다. 어쩌면 분명히해야합니다. 원래 게시물에서 8MHz가 아닌 20MHz 클록을 사용 하고 있으며 PWM이 필요하지 않다고 언급했습니다. .

PWM 모드가 2MHz 출력에서 ​​작동하지 않기 때문에 충분한 출력 주파수를 제공하는 유일한 모드는 CTC 모드 인 것 같습니다 . CTC 모드에서 타이머 1 출력 A 또는 출력 B를 반전시키는 방법이 있습니까?

이제 코드를 확인하기 위해 20MHz 보드 대신 표준 Arduino Uno (ATMega328, 16MHz)로 전환했으며, 이는 9 번과 10 번 핀의 CTC 모드에서 타이머가 안정적으로 유지되는 2MHz 클록 인 타이머 인 Timer입니다. 1 개의 출력 핀 :

#define tick 9
#define tock 10

void setup() {
  pinMode(tick, OUTPUT);  
  pinMode(tock, OUTPUT); 

  TCCR1A = _BV(COM1A0) | _BV(COM1B0) ;   // activate both output pins 
  TCCR1B = _BV(WGM12)| 1;                // set CTC mode, prescaler mode 1

  // various frustrating attempts to invert OC1B failed. What do I put here?

  OCR1A = 3;                             // set the counter max for 2 MHz

}

void loop() {
}

두 핀의 오실로스코프 트레이스는 동일하고 동기화되어 있습니다. 두 신호 중 하나를 반전 시키려면 어떻게해야합니까? 데이터 시트의 반전 모드는 CTC 모드에서 아무 것도 수행하지 않는 것 같습니다. 데이터 시트를 잘못 읽었습니까, 아니면 더 낮은 주파수와 PWM 모드를 사용해야합니까?

내 원래의 쿼리에 특정 "현상금"질문을 추가하려면 :
그래서 무엇 변경 나는 그것이 핀 (9) 및 상기 (11)에서 완벽하게 반전 신호를 제공하기 위해, 위의 내 코드에해야 할 16 MHz 클럭을위한 가장 높은 주파수를 여부, 즉 2MHz입니까?

나는 표준 Arduino Uno를 고수 할 것입니다. 따라서 내 홈 보드에서 오류 모드가 도입되지 않으며 arduino를 가진 사람은 위의 코드를 시도하고 내가 언급 한대로 작동하는지 확인할 수 있습니다. 필요한 것!


1
atmega8L 데이터 시트의 97-98 페이지를 보면 작동 모드 표가 있습니다. "COM21 : 0 비트는 생성 된 PWM 출력이 반전되어야하는지 (반전 또는 비 반전 PWM) 여부를 제어합니다"라고 말합니다. 우리는 당신의 성공에 게시 유지!
Vorac

미러링 된 출력에 간단한 트랜지스터 인버터를 사용하지 않는 이유는 무엇입니까?
Jonny B Good

답변:


10

ATtiny85 데이터 시트에서 :

작동 모드, 즉 타이머 / 카운터 및 출력 비교 핀의 동작은 파형 생성 모드 (WGM0 [2 : 0])와 비교 출력 모드 (COM0x [1 : 0])의 조합으로 정의됩니다. 비트. 출력 비교 모드 비트는 카운팅 시퀀스에 영향을 미치지 않지만 파형 생성 모드 비트는 영향을줍니다. COM0x [1 : 0] 비트는 생성 된 PWM 출력이 반전되어야하는지 (반전 또는 비 반전 PWM ) 여부를 제어합니다 .

표 11-5는 모드 설정 방법을 보여줍니다.

Mode   WGM  WGM  WGM  Timer/Counter Mode    TOP      Update of    TOV Flag
c0     02   01   00   of Operation                   OCRx at      Set on
==========================================================================
0      0    0    0    Normal                0xFF     Immediate    MAX(1)
1      0    0    1    PWM, Phase Correct    0xFF     TOP          BOTTOM
2      0    1    0    CTC                   OCRA     Immediate    MAX
3      0    1    1    Fast PWM              0xFF     BOTTOM       MAX
4      1    0    0    Reserved                                  
5      1    0    1    PWM, Phase Correct    OCRA     TOP          BOTTOM
6      1    1    0    Reserved                                  
7      1    1    1    Fast PWM              OCRA     BOTTOM       TOP

빠른 PWM 모드 (모드 3 또는 모드 7)가 필요합니다. 듀티 사이클을 변경하려고하는 것처럼 들리면 OCRA를 설정하여 모드 7을 원하고 듀티 사이클을 변경하십시오.

표 11-3은 고속 PWM 모드에 대한 비교 출력 모드를 설정하는 방법을 보여줍니다.

COM0A1/   COM0A0/
COM0B1    COM0B0     Description
===============================================================================
0         0          Normal port operation, OC0A/OC0B disconnected.
0         1          Reserved
1         0          Clear OC0A/OC0B on Compare Match, set OC0A/OC0B at BOTTOM
                     (non-inverting mode)
1         1          Set OC0A/OC0B on Compare Match, clear OC0A/OC0B at BOTTOM
                     (inverting mode)

즉, COM0A1 : COM0A0 = 0b10을 설정하여 타이머 값 == OCR0A 인 경우 OC0A 출력을 낮게 설정하고 타이머 값 == 0x00 인 경우 높음을 설정할 수 있습니다. 또는 COM0A1 : COM0A0 = 0b11을 설정하여 반대로하십시오. OC0B, OCR0B, COM0B0, COM0B1도 마찬가지입니다.

PWM 주파수는 I / O 클록 (8MHz가 사용자에게 적합 함)과 타이머 프리스케일러 설정에 의해 결정됩니다. 그리고 고속 PWM 모드의 경우 방정식은 f_clk_IO / (N * 256)으로 표시됩니다.

따라서 OCR0A와 OCR0B를 동일한 값으로 설정하고 COM0A1 : COM0A0 = 0b10 및 COM0B1 : COM0B0을 0b11로 설정하여 "정상"극성에 OC0A를 사용하고 "반전"극성에 OC0B를 사용할 수 있습니다.

최신 정보

출력을 최대한 빨리 토글하고 16MHz에서 작동하는 Mega328을 사용하는 경우 CTC 작동 모드를 통해 다음과 같은 스위칭 주파수를 얻을 수 있습니다.

f_OCnA = f_clk_IO / (2 * N * [1 + OCRnA) = 16e6 / (2 * 1 * [1 + 1]) = 4MHz

고속 PWM 모드를 사용하면 다음 위치에서 핀을 토글 할 수 있습니다.

f_OCnxPWM = f_clk_IO / (N * [1 + TOP]) = 16e6 / (1 * [1 + 1]) = 8MHz

그래서 나는 여전히 당신이 빠른 PWM 모드를 원한다고 생각합니다. 특히 50 % 듀티 사이클에 대해 OCR0A = OCR0B = 0x80 인 모드 3. 그리고 OC0A와 OC0B의 두 파형을 서로 반전 시키려면 COM0A 비트를 0x3으로, COM0B 비트를 0x2로 설정하십시오.

업데이트 # 2 Mega328 추가이 Arduino 코드를 사용해보십시오.

#define tick 9
#define tock 10

void setup(){

  pinMode(tick, OUTPUT);  
  pinMode(tock, OUTPUT); 

  // Setup Waveform Generation Mode 15
  // OC1A Compare Output Mode = inverting mode
  // OC1B Compare Output Mode = non-inverting mode
  // Timer Prescaler = 1
  // TOP = OCR1A = 1

  //COM1A[1:0] = 0b11, COM1B[1:0] = 0b10, WGM1[1:0] = 0b11
  TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);

  //WGM1[3:2] = 0b11, CS1[2:0] = 0b001
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

  OCR1A = 0x0001;
  OCR1B = 0x0001;
}

void loop(){

}

이것을 조금 씹어보고 작동하는지 봅시다. 감사합니다.
흥미 진진한 프로젝트

오늘 시도하기 위해 답을 다시 읽은 후에 몇 가지 잘못된 가정이 나타납니다. "(8MHz는 당신처럼 들립니다)"가 아니라 20MHz 클럭을 지정 했습니다 . 또한 PWM 펄스 폭 변동이 필요하지 않다고 지정 했으므로 "듀티 사이클을 변경하려는 경우 어디에서나 소리가 나는지 " 를 추측 한 부분이 확실하지 않습니다 .
흥미로운 프로젝트

@ExcitingProjects "ATTiny85 PCB에는 8MHz 크리스털이 있으며 안정적으로 작동합니다." 내 대답은 ATtiny85와 관련이 있습니다. 귀하의 업데이트 된 질문에 대한 답변으로 답변을 시도하겠습니다.
vicatcu

@vicateu 감사합니다. 단계가 빠지지 않으면 CTC 모드에서 반전 모드가 효과가없는 것처럼 보이므로 질문을 업데이트했습니다.
흥미 진진한 프로젝트

ATmega328 데이터 시트의 @ExcitingProjects : "비 PWM 모드의 경우 COM0x1 : 0 비트는 출력이 비교 일치에서 설정, 해제 또는 토글되어야하는지 여부를 제어합니다"
vicatcu

1

ATtinyX5 제품군에는 내부에 PLL이 있습니다.

내부 PLL을 사용하여 CPU 클럭에 전원을 공급하고 XTAL없이 16Mhz를 갖습니다. 핀이 5 개 밖에 없으므로 귀중합니다. (재설정 핀을 세지 않습니다). 또한 하나의 PLL'ed PWM (OCR1B)은 선택적인 무료 출력으로 XTAL 핀에서 실행됩니다. 16Mhz Xtalless ATtiny에 맞게 퓨즈를 조정하기 만하면됩니다. 또는 CPU를 8Mhz에서 실행하지만 퓨즈를 변경하지 않고 64Mhz 클럭으로 PWM을 실행하십시오.

최대 64Mhz 클럭 PWM (그러나 1 비트 분해능)을 가질 수 있습니다. 또는 8 비트 해상도에서 125Khz. OCR1C 레지스터를 줄이면 PWM 해상도를 줄이고 속도를 높일 수 있습니다.

1Mhz의 경우 OCR1C를 63으로 설정해야합니다. 2Mhz의 경우 OCR1C를 31로 설정해야합니다. 4Mhz의 경우 OCR1C를 15로 설정해야합니다. ...

이 코드로 PLL을 활성화하십시오.

PLLCSR |= (1 << PLLE);           //Start PLL
while( !(PLLCSR & (1<<PLOCK)) ); //Wait for PLL lock
//PLLCSR |= (1<<LSM );           //Low Speed PLL that clocks 32Mhz, not 64Mhz
PLLCSR |= (1 << PCKE);           //Enable PLL

이제 "OCR1B0 / OCR1A0"PWM에 64Mhz 클럭이 있습니다.

또한 미러링 된 출력에 대해 OCR1 [A / B] 0 및 XOCR1 [A / B] 0을 조정할 수 있습니다.

if(0){ //Synch mode
     //OCR1A & XOCR1A enable for Synch operation but not allow odd PWM values!
     TCCR1 |= (1 << PWM1A) | (0 << COM1A1) | (1 << COM1A0); 
     //Also ATtinyX5 has "Dead Time Generator", use it ;)
     DTPS1 = 3;   //8x Prescaler for dead time generator (maximum)
     DT1A = 0xff; //Clk dead on both channels (maximum)
     }
   else
     TCCR1 |= (1 << PWM1A) | (1 << COM1A1) | (0 << COM1A0);  //ONLY OCR1A enabled

OCR1A = 1을 설정하면 Dead Time Generator가 PWM 출력을 소모합니다. 데드 타임보다 높은 값이 필요합니다.

문안 인사,

에르 뎀

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.