WinAvr в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
OKF
Это не хвост, это антенна
Сообщения: 1385
Зарегистрирован: Вт июн 07, 2011 08:03:18

Re: WinAvr в вопросах и ответах

Сообщение OKF »

[uquote="Jack_A",url="/forum/viewtopic.php?p=4631647#p4631647"]... но заняться этим уже силов нет, и стимула. Добить бы как-то оставшиеся Тиньки, и то было бы хорошо.[/uquote]"Любил я книги, выпивку и женщин.
И большего у бога не просил.
Теперь азарт мой возрастом уменьшен.
Теперь уже на книги нету сил."
И. Губерман.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

Хотя WinAvr сильно устарел и вряд ли эта ветка имеет большую актуальность, последние сообщения ну совсем оффтоп...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: WinAvr в вопросах и ответах

Сообщение Jack_A »

Точно. Удалить на фиг. И этот пост - тоже.
Mea culpa. Это я направил тему в офф. топку. Больше постараюсь не буду.
Последний раз редактировалось Jack_A Пт окт 04, 2024 22:46:52, всего редактировалось 1 раз.
Изображение
OKF
Это не хвост, это антенна
Сообщения: 1385
Зарегистрирован: Вт июн 07, 2011 08:03:18

Re: WinAvr в вопросах и ответах

Сообщение OKF »

[uquote="ARV",url="/forum/viewtopic.php?p=4632046#p4632046"]Хотя WinAvr сильно устарел и вряд ли эта ветка имеет большую актуальность, последние сообщения ну совсем оффтоп...[/uquote]
Последнее время на форуме ТАКАЯ активность! Хорошо хоть кто то что то пишет...
Базилюк
Нашел транзистор. Понюхал.
Сообщения: 159
Зарегистрирован: Чт сен 19, 2024 19:18:28

Re: WinAvr в вопросах и ответах

Сообщение Базилюк »

А это общая тенденция к умиранию форумов - Казус, Изиэлектроникс, Электроникс. Это вообще нынче такая тенденция, что молодняк не желает учиться и делать что-то материальное, они желают развозить еду и выдавать товары на пунктах выдачи Озона.
Раньше в юности я еще увлекался 3D-моделированием. Сейчас эта тема вообще полностью умерла. Раньше я думал, что новое поколение будет намного умнее меня. А оказалось, что я в то время знал больше, чем молодняк сейчас при наличии этих ваших интернетов.
Аватара пользователя
BDDW
Открыл глаза
Сообщения: 68
Зарегистрирован: Пн май 04, 2015 12:30:18

Re: WinAvr в вопросах и ответах

Сообщение BDDW »

Доброго времени суток!
Большое спасибо всем ответившим.
Извиняюсь за долгое отсутствие. Дело в том, что это любительская конструкция "выходного дня". И все это время я пытался найти баги в программе опираясь на прочитанное в этой теме.
Кое что получилось. Всемогущий volatile - частично помог. Я пересмотрел всю программу и сделал все глобальные переменные используемые в прерываниях volatile. В результате стал нормально работать энкодер (раньше "заедал"). Заработала функция определения мощности. Но, при компиляции Optimize debugging experience (-Og) - глючит. Постоянно определяет мощность ТЭН2. При компиляции Optimize for size (-Os), Optimize most (-O3), Optimize more (-O2) - нормально. При Optimize (-O1) - глюки с выводом float (ну, и бог с ним, это ерунда).
Далее я решил перенести функцию определения мощности в библиотеку. И.... все! Не работает...
header file:
Спойлер#ifndef INCFILE_H_
#define INCFILE_H_

#define F_CPU 25000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <avr/eeprom.h>
#include "lcd2004x4.h"
#include "periphericals.h"
#include "Uart.h"
#include "pzem004t.h"
#include "wire.h"
#include "ds18b20.h"
#include "EEprom.h"

volatile uint8_t lcd_data[20][4]; //массив для вывода на дисплей. Используется в lcd2004
volatile uint8_t uart_data[26]; //массив для входящих данных UART. Используется в UART
volatile float power_percent[3]; //проценты от мощности

volatile uint8_t address_pzem004t; //адрес PZEM-004t
volatile uint8_t request_pzem; //переменная запроса PZEM-004

volatile uint8_t data_count; //счетчик для массива uart_data[26]. Используется в UART
volatile uint8_t response_time; //счетчик времени ожидания ответа от PZEM-004t. Используется в PZEM-004t

#endif /* INCFILE_H_ */
Текст функции:
Спойлерfloat Power_Measurement (void)
{
float min_power = 1000000000; //минимальная мощность
uint8_t cycle_timer = 0;
uint8_t cycle_timer0 = 0;
request_pzem = 0;
enable_sync;
do
{
if (request_pzem)
{
if (PZEM_response())
{
request_pzem = 0;
power_percent[0] = (float)PZEM_Voltage()/10; //измеренное напряжение
power_percent[1] = (float)PZEM_Current()/1000; //измеренный ток
power_percent[2] = (float)PZEM_Power()/10; //измеренная мощность
if (PZEM_Current() != 0)
{
temperatura = power_percent[0]*power_percent[1]; //вычисленная мощность
power_percent[1] = temperatura/100; //ошибка
power_percent[0] = temperatura-power_percent[1]; //min (вычисленная мощность - ошибка)
power_percent[1] += temperatura; //max (вычисленная мощность + ошибка)
if ((power_percent[2]<power_percent[1]) && (power_percent[2]>power_percent[0]))
{
if (min_power > power_percent[2]) min_power = power_percent[2];
cycle_timer++;
}
}
else cycle_timer0++;
}
}
if (cycle_timer0 == 10)
{
cycle_timer = 10;
min_power = 0;
}
} while (cycle_timer < 10);
disable_sync;
return min_power;
}
Для того, что бы не плодить лишние переменные, я использую массив power_percent[3], кторый использульзуется у меня при работе основной программы. А пременную - volatile float temperatura (температура радиатора определенную в main.c и так, же используемую основной программой), я заменяю на float calc_power, которую определяю в функции Power_Measurement.

[uquote="Just_Fluffy",url="/forum/viewtopic.php?p=4629780#p4629780"]BDDW, еще обратите внимание, сколько ОЗУ у вас занято. Иногда бывает, что стек наползает на область данных и начинаются интересные глюки )[/uquote]
Я то же на это грешу. Как видно добавление нового float - дает глюки.
А как можно на пальцах прикинуть этот стек?
Используется ATmega168. Вот данные компилятора:
Спойлер// Optimize (-O1)
// Program Memory Usage : 8468 bytes 51,7 % Full
// Data Memory Usage : 163 bytes 15,9 % Full
// Warning: Memory Usage estimation may not be accurate if there are sections other than .text sections in ELF file
// EEPROM Memory Usage : 310 bytes 60,5 % Full

// Optimize more (-O2)
// Program Memory Usage : 8766 bytes 53,5 % Full
// Data Memory Usage : 163 bytes 15,9 % Full
// Warning: Memory Usage estimation may not be accurate if there are sections other than .text sections in ELF file
// EEPROM Memory Usage : 310 bytes 60,5 % Full

// Optimize most (-O3)
// Program Memory Usage : 10758 bytes 65,7 % Full
// Data Memory Usage : 163 bytes 15,9 % Full
// Warning: Memory Usage estimation may not be accurate if there are sections other than .text sections in ELF file
// EEPROM Memory Usage : 310 bytes 60,5 % Full

// Optimize for size (-Os) - мелкие глюки с выходом из режима функции
// Program Memory Usage : 8428 bytes 51,4 % Full
// Data Memory Usage : 163 bytes 15,9 % Full
// Warning: Memory Usage estimation may not be accurate if there are sections other than .text sections in ELF file
// EEPROM Memory Usage : 310 bytes 60,5 % Full

// Optimize debugging experience (-Og) - глючит. Постоянно определяет мощность ТЭН2
// Program Memory Usage : 8592 bytes 52,4 % Full
// Data Memory Usage : 163 bytes 15,9 % Full
// Warning: Memory Usage estimation may not be accurate if there are sections other than .text sections in ELF file
// EEPROM Memory Usage : 310 bytes 60,5 % Full
Как видно, не сильно занята память.
P.S. Программа довольно таки большая, по этому я ее тут не выкладываю. Если кто то захочет с ней разобраться - то выложу
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

1. Выкладывать не надо: если вы пытаетесь исправить проблемы бездумной расстановкой volatile, то в вашем коде никто ковыряться не захочет.
2. Ваше упоминание volatile для всех переменных, используемых в прерываниях, вы сопроводили кусочком кода, где таковыми помечены массивы вывода на ЖКИ... Это не то, чтобы плохо, это категорически неприемлемо - из прерываний выводить на ЖКИ! Если, конечно, я прав (код ваш смотрел 3 секунды)
3. Расход стека проще всего определить при помощи протеуса. Если там запустить свою программу на некоторое время, а потом поставить на паузу и открыть окно просмотра RAM, можно элементарно понять, сколько жрет стек. Стек будет в виде мусора в конце памяти, а от начала будут рабочие переменные. Если между ними будет достаточно много нулевых ячеек, стек не переполняется и не налезает на переменные. А вот если этого промежутка не будет, сливай воду...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
BDDW
Открыл глаза
Сообщения: 68
Зарегистрирован: Пн май 04, 2015 12:30:18

Re: WinAvr в вопросах и ответах

Сообщение BDDW »

[uquote="ARV",url="/forum/viewtopic.php?p=4638994#p4638994"]1. Выкладывать не надо: если вы пытаетесь исправить проблемы бездумной расстановкой volatile, то в вашем коде никто ковыряться не захочет.[/uquote]
Нет. Я именно проверил все глобальные переменные, которые изменяются в прерываниях и их сделал volatile.
[uquote="ARV",url="/forum/viewtopic.php?p=4638994#p4638994"]2. Ваше упоминание volatile для всех переменных, используемых в прерываниях, вы сопроводили кусочком кода, где таковыми помечены массивы вывода на ЖКИ... Это не то, чтобы плохо, это категорически неприемлемо - из прерываний выводить на ЖКИ! Если, конечно, я прав (код ваш смотрел 3 секунды)[/uquote]
Нет. Я этого не делаю. Я из прерывания могу изменять содержание того или иного поля массива вывода на ЖКИ. А вывожу в основном цикле.
[uquote="ARV",url="/forum/viewtopic.php?p=4638994#p4638994"]3. Расход стека проще всего определить при помощи протеуса. Если там запустить свою программу на некоторое время, а потом поставить на паузу и открыть окно просмотра RAM, можно элементарно понять, сколько жрет стек. Стек будет в виде мусора в конце памяти, а от начала будут рабочие переменные. Если между ними будет достаточно много нулевых ячеек, стек не переполняется и не налезает на переменные. А вот если этого промежутка не будет, сливай воду...[/uquote]
Я, к сожалению, не пользуюсь протеусом. А как нибудь по другому можно?
codenamehawk
Вымогатель припоя
Сообщения: 527
Зарегистрирован: Вт фев 09, 2010 17:52:26

Re: WinAvr в вопросах и ответах

Сообщение codenamehawk »

BDDW писал(а):Я, к сожалению, не пользуюсь протеусом.
Если вы не отладили, то очевидно что бы не посоветовать то вы этим не пользуетесь...
В протеусе удобно отладить программу или сразу всю или хотя бы сложные куски.

"AVRStudio" пробовали?

Если подозрения на стек, возьмите похожий проц помощнее и проверьте на нем.
Аватара пользователя
BDDW
Открыл глаза
Сообщения: 68
Зарегистрирован: Пн май 04, 2015 12:30:18

Re: WinAvr в вопросах и ответах

Сообщение BDDW »

[uquote="codenamehawk",url="/forum/viewtopic.php?p=4639212#p4639212"]Если вы не отладили, то очевидно что бы не посоветовать то вы этим не пользуетесь...
В протеусе удобно отладить программу или сразу всю или хотя бы сложные куски.[/uquote]
Я знаю про протеус. И как то пытался его ставить. Но у меня ничего не получилось.

[uquote="codenamehawk",url="/forum/viewtopic.php?p=4639212#p4639212"]"AVRStudio" пробовали?[/uquote]
Для отладки каких ни будь кусков программы - пользуюсь. А вот как всю программу отладить??? Как имитировать внешние прерывания и другие входящие сигналы?
В протеусе - понятно. А тут как?
[uquote="codenamehawk",url="/forum/viewtopic.php?p=4639212#p4639212"]Если подозрения на стек, возьмите похожий проц помощнее и проверьте на нем.[/uquote]
Да. Можно поставить ATmega328. Но, хотелось бы разобраться с тем, что так разносит стек аж на 75% памяти. У меня переменными занято всего 163 байта из 1024.
codenamehawk
Вымогатель припоя
Сообщения: 527
Зарегистрирован: Вт фев 09, 2010 17:52:26

Re: WinAvr в вопросах и ответах

Сообщение codenamehawk »

BDDW писал(а):Но, хотелось бы разобраться с тем, что так разносит стек аж на 75% памяти.
Откуда узнали?
BDDW писал(а):Я знаю про протеус. И как то пытался его ставить. Но у меня ничего не получилось.
С процессором тоже не получилось, но пробуете, а протеус бросили.
BDDW писал(а):Можно поставить ATmega328. Но, хотелось бы разобраться с тем,
Так это только для того, чтобы проверить, а не просто заменить на более мощный.
BDDW писал(а):А вот как всю программу отладить??? Как имитировать внешние прерывания и другие входящие сигналы?
Все просто или вручную установив нужный бит в нужном регистре или подключить модуль протеуса, а отладку делать в студио(но работает в старой версии студии).
BDDW писал(а):аж на 75% памяти
Библиотеку для работы с float подключили?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

[uquote="BDDW",url="/forum/viewtopic.php?p=4638969#p4638969"]Если кто то захочет с ней разобраться - то выложу[/uquote]
давайте архивом весь проект, полюбопытствую, что там такое вы наделали.
только дополнительно описание задачи какое-то, что ли. если есть, конечно.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
BDDW
Открыл глаза
Сообщения: 68
Зарегистрирован: Пн май 04, 2015 12:30:18

Re: WinAvr в вопросах и ответах

Сообщение BDDW »

[uquote="codenamehawk",url="/forum/viewtopic.php?p=4640463#p4640463"]
BDDW писал(а):Но, хотелось бы разобраться с тем, что так разносит стек аж на 75% памяти.
Откуда узнали?[/uquote]
Это просто мои предположения. Компилятор пишет: Data Memory Usage : 163 bytes 15,9 % Full.
Значит остальное может занимать стек. Про то, что стек может наползать на данные, у меня закрадывалась мысль, а ответ Just_Fluffy полностью утвердил меня в моих предположениях.
P.S. Я кажется нашел грабли!!! Стек тут не причем. Но, об этом немного позже. Будет несколько вопросов.
[uquote="codenamehawk",url="/forum/viewtopic.php?p=4640463#p4640463"]
BDDW писал(а):Я знаю про протеус. И как то пытался его ставить. Но у меня ничего не получилось.
С процессором тоже не получилось, но пробуете, а протеус бросили.[/uquote]
Там проблема, по моему, была в дистрибутиве. Просто не нашел рабочую версию. А желания "хочу, аж кушать не могу" - не было. Все получалось и без него, методами отладки в AVR Studio.
[uquote="codenamehawk",url="/forum/viewtopic.php?p=4640463#p4640463"]
BDDW писал(а):Можно поставить ATmega328. Но, хотелось бы разобраться с тем,
Так это только для того, чтобы проверить, а не просто заменить на более мощный.[/uquote]
Именно так я и хотел сделать. Просто надо пол гаража перерыть в поисках уже спаянных макеток и собрать все в кучу.
[uquote="codenamehawk",url="/forum/viewtopic.php?p=4640463#p4640463"]Библиотеку для работы с float подключили?[/uquote]
Пожалуйста, не пинайте меня сильно, но я не знаю как это сделать. Много искал, читал. В этой теме говорилось неоднократно (по моему). Где то писали, что в Microchip Studio 7.0 и последних AVR Studio она подключается автоматически.
Вы говорите про подключение про libm.a?
СпойлерИзображение
Это оно?
veso74
Поставщик валерьянки для Кота
Сообщения: 1903
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение veso74 »

Предложение: удалить float. Напряжение: в миллиВольтах, ток: в миллиамперах, мощность: в миллиВаттах, переменные: в uint32_t/unsigned long int/, а при печати просто поставьте точку там, где хотите. Таким образом, используемой памяти будет мало, будет быстро и т.д. Просто в будущем используйте float там, где необходимо.

Но с использованием float я почти уверен, что проблема не в его. Дайте либо весь код программы, либо более крупный фрагмент вашей программы /если что-то из нее "скрываете" для публичного обсуждения/. А так непонятно, в чем причина.
Аватара пользователя
BDDW
Открыл глаза
Сообщения: 68
Зарегистрирован: Пн май 04, 2015 12:30:18

Re: WinAvr в вопросах и ответах

Сообщение BDDW »

[uquote="ARV",url="/forum/viewtopic.php?p=4640888#p4640888"]давайте архивом весь проект, полюбопытствую, что там такое вы наделали.
только дополнительно описание задачи какое-то, что ли. если есть, конечно.[/uquote]
Большое спасибо за желание помочь, но мне кажется, что я нашел причину.
Дело в том, что несколько лет назад я написал такую функцию для вывода float на LCD:
Спойлерchar lcd_data[4][20]; //массив для вывода на дисплей LCD 2004
void LcdFloat(float ch, uint8_t _len, uint8_t accur, uint8_t PosCur_X, uint8_t PosCur_Y)
{
char bufer[_len];
dtostrf(ch, _len, accur, bufer);
for(uint8_t x=0; x<_len; x++) lcd_data[PosCur_Y][PosCur_X+x]=bufer[x];
}
где: ch - выводимое число
_len - кол-во выводимых знаков
accur - кол-во знаков после запятой
PosCur_X - позиция в строке
PosCur_Y - номер строки
И все, работало без замечаний.
Недавно пересмотрел эту функцию и не понял, нафига я организую массив, а потом его еще и переписываю? И решил переделать напрямую так:
dtostrf(temperatura, 5, 1, lcd_data[2]+1);
Но, дело в том, что я отвожу 5 символов для вывода температуры - 3 под целые (в том числе и для отрицательных значений), одно под запятую и одно для десятых.
А на самом деле dtostrf заполняет 6 символов. Последний символ - 0 (0x0).
И тут видно, что при использовании выше приведенной функции под массив bufer я отвожу (в данном случае) 5 байт, а заполняется 6 байт.
Можно ли, и как можно избавится от последнего нуля?

Добавлено after 38 minutes:
[uquote="veso74",url="/forum/viewtopic.php?p=4640977#p4640977"]Предложение: удалить float. Напряжение: в миллиВольтах, ток: в миллиамперах, мощность: в миллиВаттах, переменные: в uint32_t/unsigned long int/, а при печати просто поставьте точку там, где хотите. Таким образом, используемой памяти будет мало, будет быстро и т.д. Просто в будущем используйте float там, где необходимо.[/uquote]
Я делаю регулятор мощности. Имея 3 ТЭНа по 1 кВт с помощью ШИМ модулятора я могу добиться что бы отдаваемая мощность была, скажем 1200 Вт. И поддерживалась автоматически при изменении напряжения в сети.
Информацию о напряжении в сети, потребляемом токе и мощности я беру с модуля PZEM-004t. Все измеряемые им величины я получаю в uint32_t по шине UART. Так, что теоретически это возможно. А вот практически? Ведь мне туда надо будет прикрутить еще ПИД регулятор.

[uquote="veso74",url="/forum/viewtopic.php?p=4640977#p4640977"]Но с использованием float я почти уверен, что проблема не в его. Дайте либо весь код программы, либо более крупный фрагмент вашей программы /если что-то из нее "скрываете" для публичного обсуждения/. А так непонятно, в чем причина.[/uquote]
Тут мне скрывать нечего. Единственное, пинайте за "быдлокодерство".
Вложения
13.10.2024.zip
Для ATmega168
(30.22 КБ) 140 скачиваний
veso74
Поставщик валерьянки для Кота
Сообщения: 1903
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение veso74 »

(Мне нравится "рисунки" выводов МК ATmega8 в "текстовом виде" :) ).
Аватара пользователя
BDDW
Открыл глаза
Сообщения: 68
Зарегистрирован: Пн май 04, 2015 12:30:18

Re: WinAvr в вопросах и ответах

Сообщение BDDW »

А как еще писать? Всегда нужна схема перед глазами. А так, когда думаешь, руки сами чем ни будь занимаются....
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

ну, вот смотрю я на код...
скажем, видел я и похуже. у вас хотя бы комментарии по существу, более-менее просто разбираться. но... как я и предполагал, смешались в кучу кони, люди...


буду писать по мере нахождения "нюансиков".

1. Вот у вас есть функция PZEM_request, которая в свою очередь использует в цикле Uart_Transmit, которая, даже судя по названию работает с "медленным" USART (и по факту, это так)... и что, спросите вы? а то, что PZEM_request у вас вызывается из обработчика прерывания INT0!!!
вот и скажите мне, чем это отличается от ранее предвиденного мною?
это категорически неприемлемо - из прерываний выводить на ЖКИ!
да, вместо медленного ЖКИ вы выводите в еще более медленный USART...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
codenamehawk
Вымогатель припоя
Сообщения: 527
Зарегистрирован: Вт фев 09, 2010 17:52:26

Re: WinAvr в вопросах и ответах

Сообщение codenamehawk »

BDDW писал(а):Значит остальное может занимать стек.
Про то, что стек может наползать на данные, у меня закрадывалась мысль, а ответ Just_Fluffy полностью утвердил меня в моих предположениях.
У вас обоих неправильное предположение.
BDDW писал(а):Пожалуйста, не пинайте меня сильно, но я не знаю как это сделать.
То был вопрос, а не совет подключить.
Последний раз редактировалось codenamehawk Сб окт 26, 2024 22:10:58, всего редактировалось 1 раз.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

чем отличаются функции в следующем коде:

Код: Выделить всё

//Вычисление Тока
uint32_t PZEM_Current (void)
{
	uint32_t pzem_data32 = 0;
	pzem_data32 = (uart_data[7]<<8|uart_data[8])&0xFFFF;
 	pzem_data32 = (pzem_data32<<8|uart_data[5])&0xFFFFFF;
 	pzem_data32 = pzem_data32<<8|uart_data[6];
	return pzem_data32;
}

//Вычисление мощности
uint32_t PZEM_Power (void)
{
		uint32_t pzem_data32 = 0;
		pzem_data32 = (uart_data[11]<<8|uart_data[12])&0xFFFF;
		pzem_data32 = (pzem_data32<<8|uart_data[9])&0xFFFFFF;
		pzem_data32 = pzem_data32<<8|uart_data[10];
		return pzem_data32;
}

//Вычисление потребленной энергии
uint32_t PZEM_Energy (void)
{
	uint32_t pzem_data32 = 0;
	pzem_data32 = (uart_data[15]<<8|uart_data[16])&0xFFFF;
	pzem_data32 = (pzem_data32<<8|uart_data[13])&0xFFFFFF;
	pzem_data32 = pzem_data32<<8|uart_data[14];
	return pzem_data32;
}
три функции, которые делают абсолютно одинаковые действия! разница лишь в том, с какими ячейками массивов они работают! но ведь тут очевидно напрашивается ОДНА функция, которая получает в параметре номер первой рабочей ячейки, а уж остальное делает относительно этого адреса... поправьте меня, если это не так:

Код: Выделить всё

uint32_t calculate(uint8_t index){
	uint32_t data = (uart_data[index+2]<<8 | uart_data[index + 3]) & 0xFFFF;
	data = ((data << 8) | uart_data[index]) & 0xFFFFFF;
	return data << 8 | uart_data[index+1];
}
и что-то сильно-сильно мне подсказывает, что в этой функции вы решили провести низкоуровневую оптимизацию вычислений... как-то странно выглядят эти сдвиги и маски. почему-то мне кажется, что все можно было сделать гораздо проще

Добавлено after 52 seconds:
3. там дальше по коду еще много похожих "одинаковых" функций.

Добавлено after 11 minutes 49 seconds:
в общем, моё мнение однозначно: нужен глубокий рефакторинг кода. чтобы и собственное понимание задачи и пути её решения выкристаллизовалось лучше.

у вас в коде намешаны низкоуровневые операции типа обращения к портам с высокоуровневыми действиями типа расчетов полученных извне значений.
то же самое касается и "деления" кода на функции: складывается впечатление, что это делалось не путем разработки алгоритма, а путем вычленения кусков "гладкого кода" в отдельные кусочки, чтобы просто хоть как-то можно было уследить за ходом процессов... но так писать не стоит.

почитайте мою статью (правда, там движок сайта попорчен и код не красивый) о нисходящем программировании: https://simple-devices.ru/articles/7-so ... 0-16-40-05
может быть, на какие-то мысли вас натолкнет.

не знаю, что именно делает ваша программа, но, имхо, функция main должна выглядеть примерно так (кода нет, одни комменты к несуществующим функциям

Код: Выделить всё

int main(void){
  // инициализация всей периферии
  // обращение к внешней аппаратуре и инициализация её
  // подготовка данных (считывание из EEPROM? поиск там каких-то адресов и т.п.)
  // вывод на ЖКИ приветствия (или меню, заставки и т.п.)
  // запуск прерываний (это не обязательно, может, только некоторых из них)
  while(1){
    // измерения 
    // обработка измерений
    // вывод результатов
    // опрос событий EVENT (пришли данные по UART? нажаты кнопки? повернут энкодер? и т.п.)
    switch(EVENT){
      case EV_USART: // обработка данных из USART
        break;
      case EV_KBD: // обработка нажатий кнопок
        break;
      // и так далее, все события
    }
  }
}
и функции у вас должны работать с одними и теми же сущностями: если функция вычисляет, то она в порты не лезет, а если лезет в порты, то не вычисляет. как-то так.

Добавлено after 8 minutes 13 seconds:
и последнее.

не бойтесь сервиса, который предоставляет вам Си: ввод-вывод стандартными средствами сделан там вполне прилично, и, уверяю вас, сильно упростит вам жизнь.

https://simple-devices.ru/articles/7-so ... -interface вот так можно красиво работать "стандартными средствами" с ЖКИ
https://simple-devices.ru/articles/7-so ... console-io а вот так с USART

последним способом я пользуюсь уже много лет, и ни разу не пожалел. согласитесь, гораздо проще написать
printf("U=%d\nI=%d\n", U, I);
и тем самым отправить в USART две строки с значениями напряжения и тока, чем городить то же самое с помощью кучи массивов, циклов и т.п. неочевидных преобразований... 2 килобайта FLASH ради такого - не великая цена. ну и еще 2К, если никак без float в этом случае не обойтись... нервы дороже.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Ответить

Вернуться в «AVR»