Есть схема фильтра нижних частот с микроконтроллером ATMega16. Есть код, который должен реализовывать оконную функцию (хоть и кривую). Я не могу вывести дробное число на осциллограф, там почему-то 0 всегда. То есть, в коде есть строка Dout = lowADC * 1.3. Как раз выводимое значение. Если я умножаю lowADC на целое число, то выводится нормально, но при умножении на дробь выводится либо 0 (если дробь меньше 1), либо вообще что-то странное. Я пробовал поменять тип данных на float у Dout и lowADC, но результата это не дало (точнее, я не знаю, как вывести результат). Что я делаю не так? И как мне вывести дробный результат Dout?
#include <avr/io.h>
#include <stdint.h>
void ADC_INIT() // конфигурирование АЦП
{
ADCSRA |= (1<<7); // Бит ADEN=1 включение АЦП
ADCSRA |= (1<<2) | (1<<1) | (1<<0); // ADPS0..2=111, предделитель - 128
ADCSRA |= (1<<5); // ADATE=1, запуск ФЦП по прерыванию
SFIOR &= -(1<<7) & (1<<6) & -(1<<0); // ADTS2..0=010 — запуск от внеш. прерывания INT0
ADMUX &= (1<<7) | (1<<6); // выбор ИОН, 11 - внутренний ИОН 1.1В
ADMUX &= (1<<0); // выбор 0-го входа мультиплексора
ADMUX &= (1<<5); // выравние рез-та по левому краю
}
int main(void)
{
ADC_INIT();
ADCSRA |= (1<<6); // запуск преобразования
DDRD = 0xFF; // режим регистра D - выход
DDRC = 0xFF; // режим регистра C - выход
uint16_t Dout = 0; // выходное значение фильтра
static const float b0 = 0.1716787f;
static const float b1 = 0.1967263f;
static const float b2 = 0.1967263f;
static const float b3 = 0.1716787f;
// линия задержки
float x3 = 0.0;
float x2 = 0.0;
float x1 = 0.0;
float x0 = 0.0;
while (1)
{
if (ADCSRA & (1<<4)) // флаг прерывания от АЦП
{
// ADCL и ADCH - верх-й и нижн.р-ры с рез-том преобразования АЦП
uint8_t lowADC = ADCL;
uint16_t Din = ADCH << 8 | lowADC;
// двигаем регистр
x3=x2;
x2=x1;
x1=x0;
x0=lowADC;
// Считаем "отфильтрованное" значение
Dout = lowADC * 1.3;//x0*b0 + x1*b1 + x2*b2 + x3*b3;
PORTD = (uint8_t)Dout; //результат записываем в р-р порта D (мл.байт)
PORTC = (uint8_t)(Dout >> 8); // в р-р порта С записываем ст. байт
ADCSRA |= (1<<4); // Бит ADIF - флаг прерывания от АЦП
}
}
}
C/C++
Как вывести дробный результат в Proteus из скрипта на C (ATMega16)?
Для вывода дробных чисел на осциллограф в Proteus из скрипта на C (ATMega16) необходимо использовать функцию printf() с форматированием числа. Для этого нужно подключить библиотеку stdio.h и настроить вывод на нужный порт.
В вашем коде можно использовать следующий код для вывода значения Dout на порт PORTD в формате с плавающей точкой с двумя знаками после запятой:
#include <stdio.h>
// ...
while (1)
{
// ...
Dout = lowADC * 1.3;
char buf[10];
sprintf(buf, "%.2f", Dout);
printf("%sn", buf);
PORTD = (uint8_t)Dout;
// ...
}
Здесь функция sprintf() форматирует значение Dout в строку buf с двумя знаками после запятой, а функция printf() выводит эту строку на стандартный вывод, который в вашем случае должен быть настроен на порт PORTD.
Обратите внимание, что для использования функции printf() необходимо настроить вывод на нужный порт. Для этого можно использовать функцию uart_init(), которая настраивает USART на нужную скорость и форматирование.
В вашем коде можно использовать следующий код для вывода значения Dout на порт PORTD в формате с плавающей точкой с двумя знаками после запятой:
#include <stdio.h>
// ...
while (1)
{
// ...
Dout = lowADC * 1.3;
char buf[10];
sprintf(buf, "%.2f", Dout);
printf("%sn", buf);
PORTD = (uint8_t)Dout;
// ...
}
Здесь функция sprintf() форматирует значение Dout в строку buf с двумя знаками после запятой, а функция printf() выводит эту строку на стандартный вывод, который в вашем случае должен быть настроен на порт PORTD.
Обратите внимание, что для использования функции printf() необходимо настроить вывод на нужный порт. Для этого можно использовать функцию uart_init(), которая настраивает USART на нужную скорость и форматирование.
Приводить к uint8_t тут не нужно.
PORTD = Dout;
PORTC = Dout >> 8;
Зачем нужна переменная Din которая нигде не использована?
uint16_t Din = ADCH << 8 | lowADC;
Какой смысл в переменной float (x0-x3) хранить однобайтный lowADC?
А в каком формате принимает данные осцилограф? Т.е. как интрепретирует биты на портах D и С?
Где то читал что трогать два первых бита на PORTD не рекомендуют, ибо забиндены на последовательный порт.
PORTD = Dout;
PORTC = Dout >> 8;
Зачем нужна переменная Din которая нигде не использована?
uint16_t Din = ADCH << 8 | lowADC;
Какой смысл в переменной float (x0-x3) хранить однобайтный lowADC?
А в каком формате принимает данные осцилограф? Т.е. как интрепретирует биты на портах D и С?
Где то читал что трогать два первых бита на PORTD не рекомендуют, ибо забиндены на последовательный порт.
Похожие вопросы
- C++ Вычислить и вывести на экран в виде таблицы
- C++ Выведите в порядке возрастания все простые числа на отрезке [l;r]. Оформите решение в виде функции bool
- Нужна помощь в AHK скрипте..
- 8-битные таймеры-счётчики : Составить схему в Proteus и Написать код для работы микроконтроллера
- Какие из этих книг вы посоветуете прочесть в первую очередь чтобы повысить свои знания в C/C++?
- Задача по C++
- Скрипт для Clickermann
- Скрипт на юнити.
- Почему создатель Linux Линус Торвальдс называет C++ ужасным языком, а ядро ОС Linux пишется только на Си?
- День добрый \[-_-]/ вопрос по вузовскому программированию на си(C)