Skip to content

Instantly share code, notes, and snippets.

@pol8139
Last active November 12, 2022 16:17
Show Gist options
  • Select an option

  • Save pol8139/9e959467ba6b202444997e2066349fff to your computer and use it in GitHub Desktop.

Select an option

Save pol8139/9e959467ba6b202444997e2066349fff to your computer and use it in GitHub Desktop.
// +-\/-+
// VDD 1| |8 GND
// LUT0-OUT PA6 2| |7 PA3
// PA7 3| |6 PA0 ~RESET UPDI
// LUT0-IN1 AIN1 PA1 4| |5 PA2
// +----+
// 4番ピンに入力されるクロックを(AVR本体のクロックとは関係なく)2番ピンから出力する。4番ピンのクロック停止を検出すると、2番ピンから5MHzが出力され、同時に5番ピンがHighになる。
// 入力2.5MHz~5MHzでうまくいった。それより外は知らない。ADCのCR時定数によって下限は2MHz、論理回路の遅延によって上限は10MHzくらいだと思う。
#ifndef __AVR_ATtiny202__
#define __AVR_ATtiny202__
#endif
#include <avr/io.h>
void disableLUT0(void)
{
CCL.CTRLA &= ~CCL_ENABLE_bm; // 一時的にCCL禁止 ↓に加えてこれも必要?
CCL.LUT0CTRLA &= ~CCL_ENABLE_bm; // 一時的にLUT0禁止 データシートにはこれだけやれば良いように書かれてる
}
void enableLUT0(void)
{
CCL.LUT0CTRLA |= CCL_ENABLE_bm;
CCL.CTRLA |= CCL_ENABLE_bm;
}
int main(void)
{
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, CLKCTRL_PEN_bm); // AVRの動作クロック10MHz
PORTA.DIR |= PIN2_bm; // 5番ピン出力設定
TCA0.SINGLE.PER = 0x0001;
TCA0.SINGLE.CTRLA |= (0x00 | TCA_SINGLE_ENABLE_bm); //プリスケーラなし、タイマー許可
TCA0.SINGLE.CTRLB |= (TCA_SINGLE_CMP1EN_bm | TCA_SINGLE_WGMODE1_bm | TCA_SINGLE_WGMODE0_bm); // WO1許可、単一傾斜PWM
TCA0.SINGLE.CMP1 = 0x0001; // 比較チャンネル1の設定→WO1はデューティ比50%の5MHz
ADC0.CTRLA |= ADC_RESSEL_bm; // 分解能8bit
ADC0.CTRLC |= (/*ADC_SAMPCAP_bm | */ADC_REFSEL0_bm); // 採取容量10pF、基準電圧VDD
ADC0.MUXPOS |= ADC_MUXPOS0_bm; // AIN1(4番ピン)入力
ADC0.CTRLA |= ADC_ENABLE_bm; // ADC許可
CCL.LUT0CTRLA |= CCL_OUTEN_bm; // LUT0(2番ピン)出力許可、PORTA.DIRで出力として設定は不要
CCL.LUT0CTRLB = (CCL_INSEL12_bm | CCL_INSEL10_bm); // LUT0入力1をIO(4番ピンであるLUT0-IN1)、LUT0入力0をMASK(0固定)
CCL.LUT0CTRLC = 0x00; // LUT0入力2をMASK(0固定)
CCL.TRUTH0 |= 0b11001100; // 真理値表の設定、LUT0入力1をそのまま出力
enableLUT0();
while(1) {
static uint8_t res = 0;
static uint8_t mode_before = 0;
ADC0.COMMAND |= ADC_STCONV_bm;
loop_until_bit_is_clear(ADC0.COMMAND, ADC_STCONV_bp);
res = ADC0.RES;
if (res < 32 || 223 < res) { // ADCの結果がVDDの半分前後から離れている→クロック入力が停止
if(mode_before == 0) {
disableLUT0();
CCL.LUT0CTRLB = CCL_INSEL13_bm; // LUT0入力1をTCA0(TCAのWO1)
enableLUT0();
PORTA.OUT |= PIN2_bm;
}
mode_before = 1;
} else {
if(mode_before == 1) {
disableLUT0();
CCL.LUT0CTRLB = (CCL_INSEL12_bm | CCL_INSEL10_bm); // LUT0入力1をIO(4番ピンであるLUT0-IN1)
enableLUT0();
PORTA.OUT &= ~PIN2_bm;
}
mode_before = 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment