Snake93 писал(а):
Отправляю 8 старших битов, так как USART не может передать все 10.
может тогда передать 2 раза по 5 бит? Или передавать 9 бит?..
Поскольку АЦП записывается в 8битный регистр ADCW=ADCL+ADCH
я записал 8 старших битов в ADCH , а два младших бита в ADCL
Передаю только ADCH . Точность высокая не нужна) Достаточно хорошо всё работает.
В данный момент всё работает без прерываний и последовательно.
Но возникла проблема вывода на индикаторы.
я с помощью цикла while(1) пытался осуществить динамическую индикацию, но кончается тем что МК начинает выдавать ошибки.
При увеличении задержки между переключением индикатором, показывает последовательно, но , всё же не динамическая)
Вот и код:
Спойлер#define F_CPU 8000000UL
#include <mega8.h>
#include <delay.h>
Да, всё достаточно просто и нелепо. Но для начала нормально)
Конечно можно использовать семисегментные индикаторы с 5 входами (4 декодер на сегменты и 1 общий катод) , тогда можно просто задействовать 12 ножек ))) и всё будет одновременно.
Тут весь вопрос синхронизации двух МК. Сначала надо определиться с протоколом передачи массива данных. Есть два варианта:
Передавать просто числа. Тогда нужно передачу жестко привязать к кол-ву передаваемых байт. Как только приемник принимает первый байт, запускается программный счетчик и начинается прием последующих байт с заранее определенным количеством. Как только счетчик дошел до значения макс. кол-ва байт он сбрасывается и отсчет начинается сначала. Но в этом варианте возможны и даже очень вероятны сбои и это очевидно.
Второй вариант - передавать по USART не просто числа, а ASCII коды, т.е. символы. Тогда можно задать стартовую последовательность пакета данных, например, символ S (т.е. передавать его ASCII код). И тогда приемник, встретив такой код в пакете данных поймет, что начинается передача пакета, начинает интерпретировать все следующие символы, как ASCII коды соответствующих чисел и принимает ровно столько байт сколько нужно (опять же необходим программный счетчик). Тогда все синхронизация сводится к передаче условия старт. Таким макаром (передачей ASCII кодов) можно организовать сложный протокол, как душе угодно, вариантов куча, вплоть до ответа приемника передатчику, типа ПРИНЯЛ, НЕ ПРИНЯЛ, с повторной передачей пакета, если не принял (здесь необходимо будет передавать контрольную сумму для всего пакет, как понятно). Это повысит надежность канала связи, что для медицинского прибора является определяющим фактором. Для преобразования числа в ASCII код можно использовать функцию itoa. Допустим ты прочитал из датчика число 32767 (максимальное положит. число для itoa). Тогда нужно заранее определить массив на 6 цифр, который будет передаваться через функцию itoa (шестой элемент массива отводится под символ /0 - конец строки, который itoa сама добавит в этот массив), а если предполагаютя и отрицательный числа, то создать массив на 7 элементов, первым символом пойдет знак "-"). Функция itoa заполнит твой массив ASCII кодами и поставит в конце /0 (т.е. массив будет выглядеть вот так: 83, 82, 87, 86, 87, 0 - итого шесть элементов,). Вот и передвай этот массив по USART. Тогда у тебя появится еще один элемент синхронизации - пустой символ /0 (код 0). Можно приемным МК еще и к нему привязаться. Понимаешь? Вообщем я же говорю здесь вариантов куча.
В целом понятно) Но на данном этапе для меня это сложно осуществить.
Пока всё будет примитивно, просто и реально. Передача идёт по USART-у. И сигнал, поступая на приём МК2 сразу же выводит подсчитанное число на индикаторы.
Индюкацию ты делаешь НЕПРАВИЛЬНО! У тебя много времени уходит на неё. Да и в целом, мне кажется программа структурирована неправильно. Ну, что называется каждый др*чит, как он хочит . Мой тебе совет: Организуй прерывание с частотой этак 250 Гц чтобы марцание динамической индикации не было заметно и в прерывании каждый раз гаси предыдущий сегмент и зажигай последующий) В этом случае тебе и библиотека задержек не потребуется и программка по сути дела должна весить меньше)
Вот пример)
неправильный пример. в примере переменная n будет скакать от значения 0 к значению 1 и обратно. подумайте почему, VanyaSV.
И эту кучу условий я бы сменил на конструкцию switch - case.
ibiza11 писал(а):неправильный пример. в примере переменная n будет скакать от значения 0 к значению 1 и обратно. подумайте почему, VanyaSV.
я не прав в том, что объявляю переменную в обработке прерываний. Её надо сделать глобальной. Но скакать в пределах от 0 к 1 она не будет, т.к. она к нулю не преравнивается
ibiza11 писал(а):И эту кучу условий я бы сменил на конструкцию switch - case.
для каждой подпрограммы будете счетчики делать глобальными переменными - букв не хватит для названий. Да и читаемость кода ухудшается.
Это то же самое, что бездумно ставить volatile перед каждой переменной.
SIGNAL(SIG_OVERFLOW1) // К примеру использовать таймер-счётчик1
ох знал бы я как прерываниями и счётчиками пользоваться))) было бы всё проще.
на данный момент необходимо за 7 дней всё сделать.
Так что, завтра продолжу изготовление макетной платы.
А вечером или в понедельник планирую заняться кодом.
Пока главное напряжение , которое идёт на АЦП, оцифровать, передать и вывести на индикаторы. Что в принципе и получается, правда плохо работает индикация.
Ещё надо продумать реализацию термометра на терморезисторе, чтобы как раз-таки изменения напряжения снималось тем самым АЦП
Добрый вечер Котам!
Нужна помощь!!!! нужно сделать усреднение данных АЦП ,никак не могу справиться с задачей.
union adcu
{
unsigned char byte[2];
unsigned int word;
};
unsigned int adcMCP1(void)
{ int c=0; //переменная для усреднения результата
union adcu adc_data;
for(c=0;c<10;c++) ??????????????????????
PORTB.4=0; // выбираем ацп
while (PINB.6==0); //ждем окончания преобразования
{adc_data.byte[1]=spi(0); //читаем старший байт
adc_data.byte[0]=spi(0); //читаем младший байт
PORTB.4=1; //отключаем ацп
return (adc_data.word>>3)&0xFFF; }
Курсовая работа сдана на отлично, схема спаяна. На данном этапе всё)
После праздников - доработка и доведение до ума.
Но это в Новом, 2013 году
Всем счастья и радости!