1
////////////////////////////////////////////////////////////////////////////////
2
/*! @file MSDN2060.c Firmware for Monitor SEX.
3
- Part of the MSDN firmware.
4
- Part of the Research Assistant project.
5
- Uses LUFA library written by
6
- Copyright(C) 2012, Dean Camera, dean [at] fourwalledcubicle [dot] com,
9
- Copyright(C) 2024, Dmitry K. Nelson, St.Petersburg, Russia.
10
D.Nelson@mail.ioffe.ru
11
- Copyright(C) 2016, Viktor E. Bursian, St.Petersburg, Russia.
12
Viktor.Bursian@mail.ioffe.ru
13
*///////////////////////////////////////////////////////////////////////////////
14
#include "Microsin_USB_IO.h"
15
#include "CommandParser.h"
17
#include <avr/power.h>
19
#include <avr/iousb162.h>
20
#include <avr/interrupt.h>
21
#include <util/delay.h> /* для _delay_us() */
26
#define INT6ENABLE 0b01000000
28
/* --------------------------------------------------------------------------------
29
К ножке 2 MCP3201 (IN+) подключено измеряемое напряжение
30
Вход внешней синхронизации - Бит 6 порта D (INT6)
31
Сигнал CS (активный 0) - Бит 5 порта B
32
Сигнал CLK (действие по фронту RISE) - Бит 6 порта B
33
Считывание данных - Бит 7 порта C
34
----------------------------------------------------------------------------------*/
36
uint16_t PointsNum = 100; // количество точек в кадре
37
uint16_t PointNo = 0; // номер регистрируемой точки
38
uint8_t PeriodInTicks = 10; // Число тиков (по 16 мкс) на период измерения
39
uint16_t DelayInTicks =100; // Число тиков (по 1/2 мкс) на задержку
40
uint16_t AdcResult; // 12 бит
43
void ReadMCP3201ADC ()
47
// начальное состояние у CLK 0, у CS 1.
48
PORTB |= ((1<<ADC_CS)|(0<<ADC_CLK));
50
//ADC_CS=0 активируем выборку чипа
51
PORTB &= ~(1<<ADC_CS);
52
_delay_us(1.0); // задержка 1 мкс
54
////////////////////////////////////////////////////
55
// передаем 3 такта инициализации
58
PORTB |= (1<<ADC_CLK); //ADC_CLK=1
59
_delay_us(1.0); // задержка около 2 мкс
60
PORTB &= ~(1<<ADC_CLK);//ADC_CLK=0
62
_delay_us(1.0); // задержка 1 мкс
64
////////////////////////////////////////////////////
65
// чтение 12 бит результата ADC, старший бит первый
69
PORTB |= (1<<ADC_CLK); //ADC_CLK=1
70
_delay_us(1.0); // задержка 1 мкс
72
if (PINC & (1<<ADC_DO))
74
PORTB &= ~(1<<ADC_CLK);//ADC_CLK=0
75
_delay_us(1.0); // задержка 1 мкс
77
PORTB |= ((1<<ADC_CS)|(0<<ADC_CLK));
82
TCNT1H = 0x00; // Обнуляем
83
TCNT1L = 0x00; // счетчик
84
TIFR0 |= (1 << OCF0A); // Сбрасываем прерывания таймера TIMER0
85
TIFR1 |= (1 << OCF1A); // Сбрасываем прерывания таймера TIMER1
86
TIMSK0 &= ~(1 << OCIE0A); // Запрещаем прерывания по таймеру TIMER0
87
TIMSK1 |= (1 << OCIE1A); // Разрешаем прерывания по таймеру TIMER1
90
int8_t ExecuteCommand0 (const char command)
94
EIFR |= INT6ENABLE; // Забыть про необработанные сигналы прерывания,
95
// случившиеся пока оно было запрещено.
96
EIMSK |= INT6ENABLE; // Разрешаем внешнее прерывание
99
EIMSK &= ~INT6ENABLE; // Запрещаем внешнее прерывание
100
TIMSK0 &= ~(1 << OCIE0A); // Запрещаем прерывания по таймеру TIMER0
101
TIMSK1 &= ~(1 << OCIE1A); // Запрещаем прерывания по таймеру TIMER1
109
int8_t ExecuteCommand2 (const char command
110
,const uint8_t argument)
114
PeriodInTicks = argument; // период измерения в тиках по 16 мкс
115
OCR0A = PeriodInTicks; // Заносим количество тактов в регистр счетчика
124
int8_t ExecuteCommand4 (const char command
125
,const uint16_t argument)
129
DelayInTicks = argument; // задержка начала измерения в тиках по 1/2 мкс
130
OCR1AH = (uint8_t)((DelayInTicks >> 8) & 0xFF); // Заносим количество тактов
131
OCR1AL = (uint8_t)(DelayInTicks & 0xFF); // в регистр счетчика
135
PointsNum = argument; // количество точек в кадре
144
int8_t ExecuteCommand8 (const char command
145
,const uint32_t argument)
152
void SetupHardware (void)
154
/* Disable watchdog if enabled by bootloader/fuses */
155
MCUSR &= ~(1 << WDRF);
158
/* Disable clock division */
159
clock_prescale_set(clock_div_1);
160
// Установки таймеров --------------------------------
162
TCCR0A = (0 << COM0A1) | // Инициализация таймера микроконтроллера TIMER0
166
(1 << WGM01) | // Режим сброса при совпадении OCR0A
169
TCCR0B = (0 << FOC0A) |
172
(0 << CS12) | // Выбор тактовой частоты
173
(1 << CS11) | // Данными битами
174
(1 << CS10); // установлена частота с делением на 64 (время на такт 16 мкс)
176
OCR0A = 0; // Заносим количество тактов в регистр счетчика
177
TIMSK0 &= ~(1 << OCIE0A); // Запрещаем прерывания по таймеру TIMER0
179
TCCR1A = (0 << COM1A1) | // Инициализация таймера микроконтроллера TIMER1
189
TCCR1B = (0 << ICNC1) |
192
(1 << WGM12) | // Режим сброса при совпадении OCR1A
193
(0 << CS12) | // Выбор тактовой частоты
194
(1 << CS11) | // Данными битами
195
(0 << CS10); // установлена частота с делением на 8 (время на такт 1/2 мкс)
197
OCR1AH = (uint8_t)((PeriodInTicks >> 8) & 0xFF); // Заносим количество тактов
198
OCR1AL = (uint8_t)(PeriodInTicks & 0xFF); // в регистр счетчика
199
TIMSK1 &= ~(1 << OCIE1A); // Запрещаем прерывания по таймеру TIMER1
200
// -----------------------------------------------------------------------------
202
// Установки для внешнего прерывания INT6 (бит 6 порта D) --------------------
203
EICRB = 0b00110000; // interrupt PCINT1 on rising edge
204
EIMSK &= ~INT6ENABLE; // Запрет прерывания
206
//настройка входа считывания данных АЦП как входа без pullup
207
DDRC &= ~(1<<ADC_DO);
208
PORTC &= ~(1<<ADC_DO);
209
//настройка выходов, у CLK начальное состояние 0,
210
// у CS начальное состояние 1.
211
DDRB |= ((1<<ADC_CS)|(1<<ADC_CLK));
212
PORTB |= ((1<<ADC_CS)|(0<<ADC_CLK));
216
void BeforeLoop (void)
226
SendNumberToUSB(PointNo);
228
SendNumberToUSB(AdcResult);
230
if (PointNo >= PointsNum) {
231
TIMSK0 &= ~(1 << OCIE0A); // Запрещаем прерывания по таймеру TIMER0
232
// Здесь можно вставить сообщение конца кадра
238
//-----------------------------------------------------------------------------
239
// Обработчик прерывания от таймера 1 (COMPA)
240
//-----------------------------------------------------------------------------
241
ISR(TIMER1_COMPA_vect){
242
sei(); // Дадим возможность обработать прерывания от USB...
243
TIMSK1 &= ~(1 << OCIE1A); // Запрещаем прерывания по таймеру TIMER1
244
EIMSK &= ~INT6ENABLE; // Запрещаем внешнее прерывание
245
TCNT0 = 0x00; // Обнуляем счетчик таймера TIMER0
246
TIMSK0 |= (1 << OCIE0A); // Разрешаем прерывания по таймеру TIMER0
251
//-----------------------------------------------------------------------------
252
// Обработчик прерывания от таймера 0 (COMPA)
253
//-----------------------------------------------------------------------------
254
ISR(TIMER0_COMPA_vect){
255
sei(); // Дадим возможность обработать прерывания от USB...
260
//------------------------------------------------------------------------------
261
/*! Обработчик прерывания INT6.
264
sei(); // Дадим возможность обработать прерывания от USB...