Например TDA7294

Форум РадиоКот • Просмотр темы - Вопросы по С/С++ (СИ)
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Чт апр 18, 2024 09:52:18

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 7581 ]     ... , , , 352, , , ...  
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Чт апр 29, 2021 20:21:28 
Поставщик валерьянки для Кота

Карма: 12
Рейтинг сообщений: 532
Зарегистрирован: Ср июл 17, 2013 13:55:57
Сообщений: 1978
Рейтинг сообщения: 0
Ну раз неожиданно, то видимо NO :)
А так видимо потому что в знаковых целых отрицательный минимум на 1 больше по модулю, чем максимум. Получаем abs(INT_MIN) = 0 из-за переполнения? Отправляю пост и иду проверять )

Добавлено after 5 minutes 51 second:
Проверил. От части я прав. Вернется NO, но abs(INT_MIN) будет не 0, а неизменно -2147483648, забыл что у abs возвращаемое значение тоже знаковое. Ну понятно, это результат работы abs просто, где оно в данном случае оборачивается просто "по кругу" на данном числе.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Чт апр 29, 2021 21:33:40 
Друг Кота
Аватар пользователя

Карма: 46
Рейтинг сообщений: 1368
Зарегистрирован: Пт авг 28, 2009 21:34:30
Сообщений: 7214
Откуда: 845-й км.
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Есть регистр CRC32->DI32. Он 16 разрядный, но я хочу данные ему скармливать побайтно. Как это написать?
(uint8_t) (CRC32->DI32) = *ptr++; - даёт ошибку "expression must be a modifiable lvalue".


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Чт апр 29, 2021 23:02:29 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
если uint8_t *ptr; то CRC32->DI32 = *ptr++; и будет побайтно получать данные

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

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


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пт апр 30, 2021 05:47:22 
Поставщик валерьянки для Кота
Аватар пользователя

Карма: 18
Рейтинг сообщений: 403
Зарегистрирован: Вт май 01, 2018 19:44:47
Сообщений: 2479
Рейтинг сообщения: 4
Настоящая байтовая запись в регистр (если он это поддерживает) делается так
Код:
*(volatile uint8_t *)&CRC32->DI32 = *ptr++;
Для побайтого чтения источника данных достаточно uint8_t *ptr;

Нужно вам побайтовое чтение или побайтовая запись читайте описание регистра вашего микроконтроллера.


Вернуться наверх
 
Организация питания на основе надежных литиевых аккумуляторов EVE и микросхем азиатского производства

Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пт апр 30, 2021 06:59:01 
Друг Кота
Аватар пользователя

Карма: 46
Рейтинг сообщений: 1368
Зарегистрирован: Пт авг 28, 2009 21:34:30
Сообщений: 7214
Откуда: 845-й км.
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Да, мне нужна "байтовая" запись. Вы же заметили, что регистр принадлежит аппаратному вычислителю CRC. А ему не всё равно, записать 0xFF или 0x00FF.

Когда я запряг под это дело DMA с байтовым обменом - всё считалось правильно, а когда попытался вот так ручками - сумма не сходилась.


Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вс май 02, 2021 11:08:31 
Поставщик валерьянки для Кота
Аватар пользователя

Карма: 18
Рейтинг сообщений: 403
Зарегистрирован: Вт май 01, 2018 19:44:47
Сообщений: 2479
Рейтинг сообщения: 0
Давеча экспериментировал со стартапом. Заметил, что GCC распознаёт паттерны копирования и установки памяти и заменяет их вызовами memcpy и memset. Вот эти два варианта после компиляции дают одинаковый результат.
Код:
extern uint32_t _sidata[], _sdata[], _edata[];
for(uint32_t *pSrc=_sidata, *pDst=_sdata; pDst!=_edata; *pDst++=*pSrc++);
    
extern uint32_t _sbss[], _ebss[];
for(uint32_t *pDst=_sbss; pDst!=_ebss; *pDst++=0);
Код:
extern uint8_t _sidata[], _sdata[], _edata[];
memcpy(_sdata, _sidata, _edata-_sdata);

extern uint8_t _sbss[], _ebss[];
memset(_sbss, 0, _ebss-_sbss);
И в обоих случаях это будет побайтовое копирование, причём и при оптимизации на скорость. Что, по меньшей мере, странно. Чтобы уговорить компилятор быстро пословно скопировать надо volatile расставить.
Код:
for(volatile uint32_t *pSrc=_sidata, *pDst=_sdata; pDst!=_edata; *pDst++=*pSrc++);
for(volatile uint32_t *pDst=_sbss; pDst!=_ebss; *pDst++=0);
Получается редкий случай, когда volatile и скорости добавляет, и размер уменьшает (если memset или memcpy больше нигде в коде не используются).


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Ср май 19, 2021 22:18:22 
Опытный кот
Аватар пользователя

Карма: 10
Рейтинг сообщений: 77
Зарегистрирован: Пт фев 27, 2015 12:00:53
Сообщений: 781
Откуда: Рязанская область
Рейтинг сообщения: 0
сделал часы с датчиком BME280
все работает как я хотел, НО зависает все (то есть на экране часы, температура, давление, влажность написаны, но не изменяются и на кнопки не реагирует) питание отключишь все работает дальше и часы не сбиваются правильно идут.
могут час или пять , полдня работать , а потом опять зависнуть. самое большое полтора суток отработали.
ардуино менял. мне кажется в коде накосячил... :facepalm: может кто глянет свежим глазом что не так! :dont_know:
Спойлер//----------,----------
#define BUTTON_1 2 // Пин клавиши 1
#define BUTTON_2 3 // Пин клавиши 2
#define BUTTON_3 4 // Пин клавиши 3

//----------
int hour,minute,second; //
int year,month,day,dayOfWeek; //
//---------- библиотеки внешние и в наших закладках-------------------------------------------------------
#include <Wire.h> // Подключаем библиотеку I2C
#include "rtc.h" // Подключаем нашу библиотеку часов
#include <EEPROM.h> // Импортируем бмблиотеку
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (133)
Adafruit_BME280 bme; // I2C
#define BME280_ADDRESS (0x77)
#include <LCD_1602_RUS.h> // подключаем библиотеку LCD_1602_RUS
LCD_1602_RUS lcd(0x27,20,4); // присваиваем имя LCD для дисплея

//---------- Инициализируем переменные-------------------------------------------------------------------------------

int h1,h0,m1,m0,s1,s0; // h1 - десятки часов, h0 - еденицы часов и так далее,
int d1, d0, mn1, mn0, day_0,day_1,day_2,month_0,month_1,month_2, sec; // d1 - десятки дней, d0 - еденицы дней и так далее...

float bme_Pressure;
float bme_Humidity;
float bme_temp, bme_temp_0,bme_temp_1,bme_temp_2;// Переменная температуры

int flag=0;
int mode=0; // моде - режим вывода на экран,

uint32_t startTime; // какая то задержка 0,025 сек
int setMode=0;
int key=0; // в зависимости от нажатых клавиш принимает значение 0, 1, 2, 3 - по номерам кнопок
int keyOld=0; // старое значение нажатой клавиши
int keySpeed=0; // переменная задает скорость повтора нажатых клавиш

unsigned long now; // переменная для счетчиков реального времени
unsigned long nov; // переменная для счетчиков гошения экрана по времени

const int timerMenu=30000; // время (в мс) перед автоматическим выходом из режима настроек
static unsigned long oldMillis = 0;

//---------- void SETUP----------------------------------------------------------------------------------------------
void setup(){ //

Serial.begin (9600); //
digitalWrite(BUTTON_1, INPUT_PULLUP); //
digitalWrite(BUTTON_2, INPUT_PULLUP); //
digitalWrite(BUTTON_3, INPUT_PULLUP); //


lcd.init();
lcd.backlight();
lcd.clear();


bool status;
status = bme.begin();
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
lcd.setCursor(0,2); lcd.print("НЕТ BME280");
while (1);
}


// Получаем данные из EEPROM
EEPROM.get(0, day_0); EEPROM.get(5, month_0); EEPROM.get(10,bme_temp_0);
EEPROM.get(15,day_1); EEPROM.get(20,month_1); EEPROM.get(25,bme_temp_1);
EEPROM.get(30,day_2); EEPROM.get(35,month_2); EEPROM.get(40,bme_temp_2);

// Вывести полученное значение
Serial.println(day_0);Serial.println(month_0); Serial.println(bme_temp_0); Serial.println("----------");
Serial.println(day_1);Serial.println(month_1); Serial.println(bme_temp_1); Serial.println("----------");
Serial.println(day_2);Serial.println(month_2); Serial.println(bme_temp_2); Serial.println("----------");
Serial.println(analogRead(0) * 5.0 / 1024.0);Serial.println(analogRead(0));
Serial.println("==================");

}

//================= void LOOP=======================
void loop(){
startTime=millis();
if (millis()-nov>2) {
getRTCDateTime();
h1=hour/10; // десятки часов
h0=hour%10; // еденицы часов
d1=day/10; // десятки дней
d0=day%10; // еденицы дней
m1=minute/10; // десятки минут
m0=minute%10; // еденицы минут
s1=second/10; // десятки секунд
s0=second%10; // еденицы секунд
}

if ((millis()-now>50000) && flag==0) {
mode=0; lcd.clear(); lcd.noBacklight();flag=1; //погасить свет экрана/показывать время тем.давл.влаж.
now=millis();
}

if (millis()-nov>5000 || second == 00) { //обращаться к датчику BME280 каждые пять сек.
bme_temp = bme.readTemperature();
bme_Pressure = bme.readPressure()/133.3;
bme_Humidity = bme.readHumidity();
nov=millis();
}

if ( hour==06 && minute==00 && second == 00 ){ // запомнить сегодняшнее, вчерашнее,позовчерашнее
day_2=day_1; day_1=day_0; day_0=day; //число
month_2=month_1; month_1=month_0; month_0=month; //месяц
bme_temp_2=bme_temp_1; bme_temp_1=bme_temp_0; bme_temp_0=bme_temp; //температура
delay(1500);
}


if(analogRead(0)<720){ //если попало питание запомнить в память
EEPROM.put(0, day_0);EEPROM.put(5, month_0);EEPROM.put(10, bme_temp_0); // Записать значение
EEPROM.put(15,day_1);EEPROM.put(20,month_1);EEPROM.put(25,bme_temp_1); // Записать значение
EEPROM.put(30,day_2);EEPROM.put(35,month_2);EEPROM.put(40,bme_temp_2); // Записать значение
lcd.clear(); Serial.println("ЗАПИСЬ");lcd.print("ЗАПИСЬ");
delay(1500);
}delay(2); //чтобы отдахнул I2C

if (mode==0){ //если экран показывает время тем.давл.влаж.
klav();disp_time(); //кнопки/обновить экран время тем.давл.влаж.
if(key==2||key==3){
now = millis(); lcd.clear();
while (millis()-now<5){
klav();
if(key==2||key==3)
lcd.clear(); mode=1; //вкл подсветку/ экран температур сегодняшнее, вчерашнее,позовчерашнее
}
key=0;
}
//----------

if(key==1){
now=millis(); lcd.clear(); // сбарсываем переменную счета таймера в (миллис)
if (millis()-now<2000){ // запускаем таймер на 2 секунду
klav();
if(key==1){
lcd.clear(); setMode=1; setUp();
}
else{
lcd.clear(); mode=1;
}
}
key=0;
}
}
//==============
if (mode==1){
klav();eeprom_lcd();
if (key==1){
now=millis(); lcd.clear(); // сбарсываем переменную счета таймера в (миллис)
while(millis()-now<5){
klav();
if(key == 1)
lcd.clear(); mode=0;
}
key=0;
}
if(key==2||key==3){
now = millis(); lcd.clear();
while (millis()-now<5){
klav();
if(key==2||key==3)
lcd.clear(); mode=0;
}
key=0;
}
}
}

//---------- ПРОЦЕДУРА ОПРОСА КЛАВИШ (кнопок)----------
void klav(){
key=0; //
if(digitalRead(BUTTON_1)==LOW) key=1; // опрашиваем клавишу 1 и если нажата переменной присваиваем 1
if(digitalRead(BUTTON_2)==LOW) key=2; // тоже самое для клавиши 2
if(digitalRead(BUTTON_3)==LOW) key=3; // тоже длч клавиши 3, при чем если нажаты все одновременно - результат будет 3
if(key!=0){ lcd.backlight(); now = millis(); flag=0; // есил клавиши нажаты ,очищаем экран .включаем свет
delay(keySpeed<8? 200:20); // устанавливаем паузу между между опросами
keySpeed++; // эта переменная ружна для того что бы через 8 циклов уменьшить паузу между опрасами с 200 до 20
} //
if(key!=keyOld) keySpeed=0; // если была смена клавиш то флаг скорости опросов сбрасываем в 0
keyOld=key; // в переменную предыдущего состояния клавиш записываем текущее состояние клавиш
}
//----------
void setUp(){
delay(500);
now = millis(); lcd.clear(); // сбарсываем переменную счета таймера в (миллис)
while (millis()-now < timerMenu){ // запускаем таймер
switch(setMode){

case 1: setUp_year(); lcd.setCursor(0,1);lcd.print("ГОД "); break;
case 2: setUp_month(); lcd.setCursor(0,1);lcd.print("МЕСЯЦ "); break;
case 3: setUp_day(); lcd.setCursor(0,1);lcd.print("ДЕНЬ "); break;
case 4: setUp_dayOfWeek();lcd.setCursor(0,1);lcd.print("НЕДЕЛЯ "); break;
case 5: setUp_hour(); lcd.setCursor(0,1);lcd.print("ЧАС "); break;
case 6: setUp_minute(); lcd.setCursor(0,1);lcd.print("МИНУТА "); break;
case 7: setUp_second(); lcd.setCursor(0,1);lcd.print("СЕКУНДЫ"); break;
case 8: return;

}
klav(); // Опрашиваем клавиши 0- не нажаты, 1-3 клавиши нажат
if(key == 1){ // если нажата
setMode++; // если нажата кнопка 1, то выходим из подпрограмы
if(setMode > 8) mode=0;
}
}
mode=0;
}
//----------
void setUp_second(){
now = millis(); lcd.clear(); // сбарсываем переменную счета таймера в (миллис)
while (millis()-now < timerMenu){ // запускаем таймер автовыхода из подпрограмы, если мы сейчас в позии секунд то таймер увеличиваем на 60 секунд
getRTCDateTime(); // считываем данные часы, минуты, секунды
lcd.setCursor(0,1);lcd.print("СЕКУНДЫ ");lcd.print(second);//высвечиваем секунды
klav(); // Опрашиваем клавиши 0- не нажаты, 1-3 клавиши нажаты
if(key == 1){ lcd.clear(); // если нажата кнопка 1, то выходим из подпрограмы
setMode = 8;return;
}
if(key == 2 || key == 3 ){ // если нажата кнопка 2,3
now = millis(); lcd.clear(); // сбрасывае счетчик автовыхода из подпрограмы

if (second > 30){
minute++; second=0;
}
setRTCDateTime();
}
if(key == 2 || key == 3){ // если нажата кнопка 3,2
now = millis();
if (second < 30){
second=0;
}
setRTCDateTime();
}
}
}
//============
void setUp_minute(){
now = millis(); lcd.clear(); // сбарсываем переменную счета таймера в (миллис)
while (millis()-now < timerMenu){ // запускаем таймер автовыхода из подпрограмы,
getRTCDateTime(); // считываем данные часы, минуты, секунды
lcd.setCursor(0,1);lcd.print("МИНУТЫ ");lcd.print(minute);
klav(); // Опрашиваем клавиши 0- не нажаты, 1-3 клавиши нажаты
if(key == 1){ // если нажата кнопка 1, то выходим из подпрограмы
lcd.clear(); setMode = 7;return;
}
if(key == 2){ // если нажата кнопка 2, то переходим к следующей позиции установки
now = millis(); lcd.clear(); // сбрасывае счетчик автовыхода из подпрограмы
if (minute < 60){
minute++; if (minute==60)minute=0;
}
setRTCDateTime();}
if(key == 3){ // если нажата кнопка 3, то меняеме значение переменной отображаемой в данной позиции
now = millis(); lcd.clear();
if (minute >-1){
minute--; if (minute==-1)minute=59;
}
setRTCDateTime();
}
}
}
//============
void setUp_hour(){
now = millis(); lcd.clear(); // сбарсываем переменную счета таймера в (миллис)
while (millis()-now < timerMenu){ // запускаем таймер автовыхода из подпрограмы,
getRTCDateTime(); // считываем данные часы, минуты, секунды
lcd.setCursor(0,1);lcd.print("ЧАС ");lcd.print(hour);
klav(); // Опрашиваем клавиши 0- не нажаты, 1-3 клавиши нажаты
if(key == 1){ // если нажата кнопка 1, то выходим из подпрограмы
lcd.clear(); setMode = 6;return;
}
if(key == 2){ // если нажата кнопка 2, то переходим к следующей позиции установки
now = millis(); lcd.clear(); // сбрасывае счетчик автовыхода из подпрограмы

if (hour < 24){
hour++; if (hour==24)hour=0;
}
setRTCDateTime();}
if(key == 3){ // если нажата кнопка 3, то меняеме значение переменной отображаемой в данной позиции
now = millis(); lcd.clear();
if (hour >-1){
hour--; if (hour==-1)hour=23;
}
setRTCDateTime();
}
}
}
//----------
void setUp_dayOfWeek(){ //

now = millis(); lcd.clear(); // сбарсываем переменную счета таймера в (миллис)
while (millis()-now < timerMenu){ // запускаем таймер автовыхода из подпрограмы, если мы сейчас в позии секунд то таймер увеличиваем на 60 секунд
getRTCDateTime(); // считываем данные часы, минуты, секунды

switch(dayOfWeek){
case 0:lcd.setCursor(0,1);lcd.print("ДЕНЬ НЕДЕЛИ");lcd.setCursor(0,2);lcd.print("ПОНЕДЕЛЬНИК");
break;
case 1:lcd.setCursor(0,1);lcd.print("ДЕНЬ НЕДЕЛИ");lcd.setCursor(0,2);lcd.print("ВТОРНИК ");
break;
case 2:lcd.setCursor(0,1);lcd.print("ДЕНЬ НЕДЕЛИ");lcd.setCursor(0,2);lcd.print("СРЕДА ");
break;
case 3:lcd.setCursor(0,1);lcd.print("ДЕНЬ НЕДЕЛИ");lcd.setCursor(0,2);lcd.print("ЧЕТВЕРГ ");
break;
case 4:lcd.setCursor(0,1);lcd.print("ДЕНЬ НЕДЕЛИ");lcd.setCursor(0,2);lcd.print("ПЯТНИЦА ");
break;
case 5:lcd.setCursor(0,1);lcd.print("ДЕНЬ НЕДЕЛИ");lcd.setCursor(0,2);lcd.print("СУББОТА ");
break;
case 6:lcd.setCursor(0,1);lcd.print("ДЕНЬ НЕДЕЛИ");lcd.setCursor(0,2);lcd.print("ВОСКРЕСЕНЬЕ");
break;
}

klav(); // Опрашиваем клавиши 0- не нажаты, 1-3 клавиши нажаты
if(key == 1){ // если нажата кнопка 1, то выходим из подпрограмы
lcd.clear(); setMode = 5;return; //
}
if(key == 2){ // если нажата кнопка 2, то переходим к следующей позиции установки
now = millis(); lcd.clear(); // сбрасывае счетчик автовыхода из подпрограмы
if (dayOfWeek < 7){
dayOfWeek++;if (dayOfWeek==7)dayOfWeek=0;
}
setRTCDateTime();
} //
if(key == 3){ // если нажата кнопка 3, то меняеме значение переменной отображаемой в данной позиции
now = millis(); lcd.clear();
if (dayOfWeek > -1){
dayOfWeek--;if (dayOfWeek==-1)dayOfWeek=6;
}
setRTCDateTime(); //запись в РТС
}
}
}
//----------
void setUp_month(){ //

now = millis(); lcd.clear(); // сбарсываем переменную счета таймера в (миллис)
while (millis()-now < timerMenu){ // запускаем таймер автовыхода из подпрограмы,
getRTCDateTime(); // считываем данные часы, минуты, секунды
lcd.setCursor(0,1);lcd.print("МЕСЯЦ");
lcd.setCursor(0,2);
if (month==1) {lcd.print("ЯНВАРЬ");}
if (month==2) {lcd.print("ФЕВРАЛЬ");}
if (month==3) {lcd.print("МАРТ");}
if (month==4) {lcd.print("АПРЕЛЬ");}
if (month==5) {lcd.print("МАЙ");}
if (month==6) {lcd.print("ИЮНЬ");}
if (month==7) {lcd.print("ИЮЛЬ");}
if (month==8) {lcd.print("АВГУСТ");}
if (month==9) {lcd.print("СЕНТЯБРЬ");}
if (month==10) {lcd.print("ОКТЯБРЬ");}
if (month==11) {lcd.print("НОЯБРЬ");}
if (month==12) {lcd.print("ДЕКАБРЬ");}
klav(); // Опрашиваем клавиши 0- не нажаты, 1-3 клавиши нажаты
if(key == 1){ // если нажата кнопка 1, то выходим из подпрограмы
lcd.clear(); setMode = 3;return;
}
if(key == 2){ // если нажата кнопка 2, то переходим к следующей позиции установки
now = millis(); lcd.clear(); // сбрасывае счетчик автовыхода из подпрограмы

if (13 > month ){
month++; if (month==13)month=1;
}
setRTCDateTime();
}
if(key == 3){ // если нажата кнопка 3, то меняеме значение переменной отображаемой в данной позиции
now = millis(); lcd.clear();
if (month >0 ){
month--; if (month==0)month=12;
}
setRTCDateTime();
}
}
}
//----------
void setUp_day(){
now = millis(); lcd.clear(); // сбарсываем переменную счета таймера в (миллис)
while (millis()-now < timerMenu){ // запускаем таймер автовыхода из подпрограмы, если мы сейчас в позии секунд то таймер увеличиваем на 60 секунд
getRTCDateTime(); // считываем данные часы, минуты, секунды
lcd.setCursor(0,1);lcd.print("ДЕНЬ ");lcd.print(day);
klav(); // Опрашиваем клавиши 0- не нажаты, 1-3 клавиши нажаты
if(key == 1){ // если нажата кнопка 1, то выходим из подпрограмы
lcd.clear(); setMode = 4;return;
}
if(key == 2){ // если нажата кнопка 2,
now = millis(); lcd.clear(); // сбрасывае счетчик автовыхода из подпрограмы
if (day < 32){
day++; if (day==32)day=1;
setRTCDateTime();}
} //
if(key == 3){ // если нажата кнопка 3,
now = millis(); lcd.clear();
if (0 < day){
day--; if (day==0)day=31;
}
setRTCDateTime();
}
}
}
//----------
void setUp_year(){
now = millis(); lcd.clear(); // сбарсываем переменную счета таймера в (миллис)
while (millis()-now < timerMenu){ // запускаем таймер автовыхода из подпрограмы, если мы сейчас в позии секунд то таймер увеличиваем на 60 секунд
getRTCDateTime(); // считываем данные часы, минуты, секунды
lcd.setCursor(0,1);lcd.print("ГОД ");lcd.print(year);
klav(); // Опрашиваем клавиши 0- не нажаты, 1-3 клавиши нажаты
if(key == 1){ // если нажата кнопка 1, то выходим из подпрограмы
lcd.clear(); setMode = 2;return;
}
if(key == 2){ // если нажата кнопка 2, то переходим к следующей позиции установки
now = millis(); lcd.clear(); // сбрасывае счетчик автовыхода из подпрограмы

if (year < 2100){
year++;
setRTCDateTime();}
} //
if(key == 3){ // если нажата кнопка 3, то меняеме значение переменной отображаемой в данной позиции
now = millis(); lcd.clear();
if (2020 < year){
year--;
}
setRTCDateTime();
}
}
}

//---------- выводит на экран температур--------------------
void eeprom_lcd()
{
lcd.setCursor(0,0); lcd.print("ДАТА");lcd.setCursor(6,0);lcd.print("ТЕМПЕРАТУРА");
lcd.setCursor(0,1);lcd.print(day_0);lcd.print(".");lcd.print(month_0);lcd.setCursor(8,1);lcd.print(bme_temp_0); lcd.print(" °");lcd.print("C");


lcd.setCursor(0,2);lcd.print(day_1);lcd.print(".");lcd.print(month_1);lcd.setCursor(8,2);lcd.print(bme_temp_1); lcd.print(" °");lcd.print("C");


lcd.setCursor(0,3);lcd.print(day_2);lcd.print(".");lcd.print(month_2);lcd.setCursor(8,3);lcd.print(bme_temp_2); lcd.print(" °");lcd.print("C");
}




//---------- на экран время----------------------------------------------
void disp_time (){

lcd.setCursor(0,0);
if (h1>0){lcd.print(h1);lcd.print(h0);}
else {lcd.print(" ");lcd.print(h0);}


//lcd.print(hour);
lcd.print(":");lcd.print(m1);lcd.print(m0);lcd.print(":");
//lcd.print(second);
lcd.print(s1);lcd.print(s0);

lcd.setCursor(10,0);
if (d1>0){lcd.print(d1);lcd.print(d0);}
else {lcd.print(" ");lcd.print(d0);}

// lcd.print(day);
lcd.print(" ");

switch (dayOfWeek) {
case 0:
lcd.print("Пн");
break;
case 1:
lcd.print("Вт");
break;
case 2:
lcd.print("Ср");
break;
case 3:
lcd.print("Чт");
break;
case 4:
lcd.print("Пт");
break;
case 5:
lcd.print("Сб");
break;
case 6:
lcd.print("Вс");
break;
case 7:dayOfWeek=0;setRTCDateTime();
break;

}



lcd.setCursor(0,1); lcd.print("Темп = ");lcd.print(bme_temp); lcd.print(" °");lcd.print("C");

lcd.setCursor(0,2); lcd.print("Давл = ");lcd.print(bme_Pressure);lcd.print(" mm");

lcd.setCursor(0,3); lcd.print("Влаж = ");lcd.print(bme_Humidity); lcd.print(" % ");
}


//---------- конец---------------------------------------------------------------


Вложения:
meteostanciya_moi.ino.hex [59.51 KiB]
Скачиваний: 147
meteostanciya_moi.zip [7.91 KiB]
Скачиваний: 147
Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пт май 28, 2021 20:26:55 
Опытный кот
Аватар пользователя

Карма: 10
Рейтинг сообщений: 77
Зарегистрирован: Пт фев 27, 2015 12:00:53
Сообщений: 781
Откуда: Рязанская область
Рейтинг сообщения: 0
ну зависает часы с датчиком ВМЕ280 хоть ты тресни...
скажите, а у меня датчик через провод (витая пара UTP 2х2х0,5 ) 3 метра подключен к ардуине, может из за этого виснуть?
или может все незадействованные ноги ардуино посадить на минус, чтобы не ловили помехи какие-нибудь
или подключить к земле, - используя параметр INPUT_PULLUP?
блоки питания менял и 5 вольтовый был , и сейчас 7,5 вольтовый через кренку, конденсатор 2200мкф, 0,1мкф стоит от какой-то тв приставки, все одно виснет...
посоветуйте , что еще бы можно сделать. :dont_know:


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пт май 28, 2021 21:26:28 
Поставщик валерьянки для Кота

Карма: 12
Рейтинг сообщений: 532
Зарегистрирован: Ср июл 17, 2013 13:55:57
Сообщений: 1978
Рейтинг сообщения: 0
Цитата:
или подключить к земле, - используя параметр INPUT_PULLUP?

Цитата:
или может все незадействованные ноги ардуино посадить на минус, чтобы не ловили помехи какие-нибудь

Это конечно полная ерунда написана. От непонимания.

Цитата:
3 метра подключен к ардуине, может из за этого виснуть?

Может. Попробуйте для начала подключить коротким проводом его. Чтобы исключить остальные проблемы.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 08, 2021 11:10:31 
Родился

Зарегистрирован: Вт июн 08, 2021 10:56:42
Сообщений: 2
Рейтинг сообщения: 0
Всем здрасте.
До этого программировал avr в Flowcode.
Я новичок в Си, месяц читаю и в большинстве всё понятно.
НО, откуда берут какой #include в каком случае, как например для задержки времени _delay_us надо включить <avr/delay.h>, но нигде не говорят где и в каком случае подключать другие файлы библиотеки и какие переменные/имена использовать из той библиотеки.
К примеру хочу I2C, какой #include< > мне для этого нужен и какие имена из него использовать и т.д.?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 08, 2021 14:09:31 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
все это берут из документации к тулчейну.

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

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


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 08, 2021 15:29:21 
Поставщик валерьянки для Кота

Карма: 12
Рейтинг сообщений: 532
Зарегистрирован: Ср июл 17, 2013 13:55:57
Сообщений: 1978
Рейтинг сообщения: 0
sakvvvvvv, если avr-gcc, то:
https://www.nongnu.org/avr-libc/user-ma ... dules.html
https://www.nongnu.org/avr-libc/user-manual/pages.html


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Ср июн 09, 2021 13:44:20 
Родился

Зарегистрирован: Вт июн 08, 2021 10:56:42
Сообщений: 2
Рейтинг сообщения: 0
все это берут из документации к тулчейну.

Тулчей, значит тулчей.

Добавлено after 49 seconds:

Это уже ближе, спасибо.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Ср июн 09, 2021 15:11:12 
Поставщик валерьянки для Кота

Карма: 12
Рейтинг сообщений: 532
Зарегистрирован: Ср июл 17, 2013 13:55:57
Сообщений: 1978
Рейтинг сообщения: 0
Цитата:
Тулчей, значит тулчей.

Тулчейн. https://en.wikipedia.org/wiki/Toolchain


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пн июн 14, 2021 10:33:50 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
что-то я не понимаю, что происходит: или у меня работает код, который работать не должен, а правильный не работает, или я чего-то не понимаю.
Код:
ISR(TIMER1_OVF_vect){
   static uint8_t   entry;
   static uint8_t   pos;
   static pos_t *scr = screen;
   regs_t   regs;

   // считаем входы
   if(++entry >= IND_RPT){
      entry = 0;
      // каждые 2 мс
      two_ms++;
      // смена разряда
      scr++;
      if(++pos >= POS_CNT){
         pos = 0;
         scr = screen;
      }
      regs.word = _BV(11+pos);
   }
   // готовим один из двух символов для вывода
   regs.word &= 0xf800;
   regs.word |= digs[scr->symbol[entry >= scr->bright]];

   // выдача в сдвиговые регистры через SPI
   SPDR = regs.bytes[1];
   while(bit_is_clear(SPSR, SPIF));
   SPDR = regs.bytes[0];
   while(bit_is_clear(SPSR, SPIF));
   // строб для защелкивания данных
   PORTB |= LOAD_PIN;
   PORTB &= ~LOAD_PIN;
}
вот такой код для динамической индикации. каждые 2 мс происходит смена разряда, а каждый заход в обработчик происходит обновление символов (символов два, сначала выводится один, а когда количество входов превысит заданное значение - другой, таким образом реализована "плавная" смена символов).

так вот, код этот РАБОТАЕТ. но, если внимательно посмотреть на него, а именно на структуру regs, то станет понятно, что работать он НЕ ДОЛЖЕН: структура локальная, значит, содержимое её при каждом новом входе не определено, а значит, строка после комментария "готовим один из двух символов для вывода" не имеет смысла - подавлять часть разрядов поля структуры для того, чтобы сохранить биты управления разрядом индикатора, нет смысла - там неизвестно что может быть! кстати, некоторые версии компилятора avr-gcc предупреждают, что переменная тут может быть не проинициализирована, некоторые этот факт игнорируют, но при оптимизации -O3 код работает после компиляции любой версией (проверял 4 разных, от 4.хх.хх до 10.хх.хх). и еще кстати, при -Os код не работает так же независимо от версии компилятора.

казалось бы, в чем беда? делаем структуру static и... и код НЕ РАБОТАЕТ!!!!!!!! :o то есть когда от прерывания к прерыванию я сохраняю состояние структуры, т.е. значение битов, управляющих разрядами индикатора, это не только не делает нерабочий код рабочим, но и полностью рушит индикацию!

может кто-нибудь пояснить, что происходит?! :shock:

да, структура regs такая:
Код:
typedef union{
   uint8_t      bytes[2];         // 2 байта для выдачи в регистры
   uint16_t      word;
} regs_t;
идея индикации следующая: старшие 5 битов в regs.word задают номер светящегося разряда индикатора, а остальные - выводимый символ (для ГРИ это 1 бит в нужном разряде). потом эти 16 бит выдаются побайтно в регистры 74HC595 и управляют индикаторами.

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

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


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пн июн 14, 2021 12:32:02 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1018
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4875
Откуда: Минск
Рейтинг сообщения: 0
В качестве предположения.

То, что код работает, хотя и не должен - можно сослаться на "везение" в том смысле, что regs всегда попадает на один и тот же определённый адрес при определённом уровне оптимизации.

А вот то, что код не работает в случае static - да, более странно. Но не может ли быть так, что доступ к "статической" структуре получается с точки зрения ассемблера более длинным, что в итоге является той каплей, что прерывание не успевает выполниться за нужное время?

Я о том, что два while() внутри прерывания при передаче по SPI могут быть "впритирку" ко времени между вызовами сосбственно прерываний.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пн июн 14, 2021 12:42:13 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
WiseLord писал(а):
Но не может ли быть так, что доступ к "статической" структуре получается с точки зрения ассемблера более длинным, что в итоге является той каплей, что прерывание не успевает выполниться за нужное время?
да, но что в таком случае может происходить? только то, что основной цикл станет выполняться очень медленно, а динамическая индикация продолжится, хоть и с некоторыми артефактами вроде разной яркости разрядов.

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

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

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

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


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пн июн 14, 2021 13:41:43 
Сверлит текстолит когтями

Карма: -10
Рейтинг сообщений: 93
Зарегистрирован: Вт авг 15, 2017 10:51:13
Сообщений: 1154
Рейтинг сообщения: 0
только то, что основной цикл станет выполняться очень медленно, а динамическая индикация продолжится, хоть и с некоторыми артефактами вроде разной яркости разрядов.
у меня же происходит вообще странное: во всех разрядах начинают "призрачно" дублироваться цифры соседних, т.е. в кажом разряде светится правильная цифра наиболее ярко, и слегка просвечивают цифры, которые на всех остальных. будто у меня команда, маскирующая "символьную" часть структуры, не выполняет свою задачу...

Что тут непонятного?
regs.word |= digs[scr->symbol[entry >= scr->bright]]; выполняется в каждом ISR.
Не знаю что такое digs, предположу что оно хранит младшие 11 бит. Тогда эти 11 бит будут верными при каждом вызове ISR.
Если эти 11 бит - карта сегментов, то она всегда будет правильной передаваться в SPI. А старшие 5 бит (позиция?) будут неправильными. И то - если других прерываний нет, то место занимаемое в стеке regs может оказаться неразрушенным (и сохраниться от момента последней правильной записи старших 5 бит). Тогда и позиция будет передаваться правильная. Но иногда (когда содержимое regs трётся в стеке другой процедурой), то позиция будет неправильная (при правильных сегментах). А значит и будет наблюдаться - в основном правильное отображение, но иногда символы будут попадать в неправильные случайные позиции. Это будет редко, поэтому светится они там будут слабо.

PS: Ожидание завершения передачи по SPI в while() внутри ISR - это конечно верх быдлокодинга... :o
Если конечно там (в МК) имеется FIFO глубиной >= 2 байта и while() ожидает не завершения передачи, а завершения записи в FIFO, то тогда - нормально.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пн июн 14, 2021 16:13:51 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
jcxz писал(а):
Что тут непонятного?
а вы посмотрите внимательно:
regs.word &= 0xf800;
regs.word |= digs[scr->symbol[entry >= scr->bright]];

младшие 11 бит в каждом прерывании меняются, а старшие 5 - только каждое 62 прерывание. то есть так должно быть, если regs будет static.
вопрос не в том, почему без static работает (хоть это и странно, но вполне логичное объяснение вы сами и дали), вопрос в том, почему со static не работает?!
ведь благодаря static старшие биты сохраняются не из-за случая в стеке/памяти, а абсолютно однозначно! то есть должно быть лучше, а по факту - становится хуже.
как это объясните?
jcxz писал(а):
Ожидание завершения передачи по SPI в while() внутри ISR - это конечно верх быдлокодинга
SPI работает на частоте вдвое меньше тактовой, т.е. передача 1 байта требует 16 тактов - пока исполнится код, организующий ожидание, пройдет половина этого интервала.
вам известны более красивые способы отправки двух байт с последующей дрыгоножной выдачей строба на классическом AVR? посоветуйте, я всегда готов учиться хорошему. а грубить я умею и сам.

чисто теоретически вывод в регистры можно делать в главном цикле, а в прерывании обойтись классическими флагами, но, боюсь, это приведет к гораздо большим проблемам с индкацией...

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

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


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 15, 2021 07:06:30 
Открыл глаза

Карма: 1
Рейтинг сообщений: 19
Зарегистрирован: Вс сен 03, 2017 19:43:57
Сообщений: 42
Рейтинг сообщения: 0
У вас структура regs определяется каждый раз при запуске прерывания и имеет в качестве данных мусор (что вы и написали).
А первое присвоение происходит в условии if. А если условие ложное то структура не заполниться и строки
Код:
   regs.word &= 0xf800;
   regs.word |= digs[scr->symbol[entry >= scr->bright]];

будут работать с мусором
Использование static заставляет компилятор оптимизировать данный код (скорее всего он выкидывает часть)


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 7581 ]     ... , , , 352, , , ...  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 22


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y