Jump to content

Recommended Posts

3 часа назад, Дмитрий Вас сказал:

в таком случае если я напишу такой код в ISR?

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

Теперь смотрите, каков должен быть алгоритм. "Плавно изменять" означает буквально "каждые N миллисекунд уменшать OCR1A на величину X, пока OCR1A не станет равно нулю". Нельзя уменьшать OCR1A в цикле while(OCR1A) OCR1A--; потому что цикл этот не завершится, пока не обнулится OCR1А, а произойдет это очень быстро, буквально за несколько милисекунд - вы не заметите никакой "плавности".

Поэтому ваш алгоритм (код) не будет выполнять нужую функцию, куда бы вы его не поместили.

Прерывание по таймеру, возникающее каждые N миллисекунд - это уже аналог цикла с нужной скоростью! Поэтому достаточно сделать так: в главном цикле проверить нажатие кнопки, и, если она нажата, установить флаг. В обработчике прерывания смотреть на этот флаг, и, если он установлен, проверять OCR1А на равенство нулю, после чего, если оно нулю не равно, уменьшать его. То есть как-то так:

volatile uint8_t flag; // это будет флаг плавного уменьшения

ISR(TIMER1_OVF_vect){ // это обработчик прерывания по переполнению таймера, вызываемый, допустим, каждые 10 мс, т.е. 100 раз в секунду
  if(flag){ // когда стоит флаг
    if(OCR1A) OCR1A--; // если OCR1A не нулевое, то уменьшаем его
  	else flag = 0; // а если уже обнулилось - снимаем флаг
  }
}

// где-то в главном цикле вы проверяете кнопку и устанавливаете флаг:
if((PIND & (1<<BD5)) == 0) flag = 1;

Я исходил из предпосылки, кто кнопка при нажатии замыкает пин МК на общий.

3 часа назад, Дмитрий Вас сказал:

я правильно понял?

Нет, не правильно. Задает значение левому операнду только оператор =, остальные операторы только возвращают значение. Ну, можно исключить ++ и -- и другие типа += или *=, которые на самом деле являются упрощенной записью сразу двух операторов, поэтому и меняют, и возвращают одновременно.

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

volatile uint16_t new_ocr;

ISR(TIMER1_OVF_vect){
  int8_t delta = 0;
  if(OCR1A < new_ocr) delta = 1;
  if(OCR1A > new_ocr) delta = -1;
  OCR1A += delta;
}

// контроль кнопки делаем макросом
#define pressed_button(x) ((PIND & (1<<(x))) == 0)

// где-то в главном цикле анализируете кнопки
if(pressed_button(PD5)) new_ocr = 0x01FF; // максимум яркости
else if(pressed_button(PD4)) new_ocr = 0; // минимум яркости

 


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

Share this post


Link to post
Share on other sites
Posted (edited)
23 минуты назад, ARV сказал:

Задает значение левому операнду только оператор =, остальные операторы только возвращают значение

Это похоже на издевательство над совершенно дезориентированным человеком @Дмитрий Вас, он даже не понимает различий между языками программирования, а вы ему советы по азам одного из языков даете, как будто чтобы понаблюдать как он вывернет это новое ЗНАНИЕ себе вовред.

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

Edited by ruhi
дополнил

Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites
16 минут назад, ruhi сказал:

Это похоже на издевательство над совершенно дезориентированным человеком

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


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

Share this post


Link to post
Share on other sites

Быстро и просто. Разработка бюджетного неизолированного источника питания на контроллере VIPer122

С помощью VIPer122 можно создавать как изолированные, так и неизолированные сетевые источники питания. Разберем самый простой и бюджетный вариант – разработку неизолированного понижающего источника питания с выходным током в несколько сотен миллиампер без трудоемких расчетов трансформаторов и компонентов обвязки.

Подробнее

4 часа назад, Дмитрий Вас сказал:

вот этому обьяснения я не находил, выходит логическое <= ВОЗВРАЩАЕТ значение? а  <   задает? 

Смотрите,  кратенько... 

"=" это оператор присваивания, он присваевает леву то что справа.

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

Поэтому операция сравнения, это тоже можно сказать некоторая функция, которая вернула результат сравнения. (Его можно присвоить  оператором присваивания какой либо переменной для дальнейшего использования, а можно и не присваивать).

Share this post


Link to post
Share on other sites

Пополнение линейки ViperPlus от STMicroelectronics

Компания ST обновила семейство ШИМ-регуляторов со встроенным ключом ViperPlus, выпустив новые бюджетные микросхемы VIPER122 и VIPER222, и микросхемы VIPER265K и VIPER267K, имеющие встроенный ключ MOSFET напряжением 1050 В. С их помощью возможно реализовать топологии: изолированный и неизолированный обратноходовой преобразователь (flyback), понижающий преобразователь (buck), повышающе-понижающий преобразователь (buck-boost).

Подробнее

Posted (edited)
4 часа назад, Дмитрий Вас сказал:

я правильно понял?

Попробую зайти с другого конца. Пока забудьте о программировании и Си.

Пусть имеется следующее арифметическое выражение:  (A+B)/B, где A=6, B=2

Чему равно это выражение?  Очевидно, что 4. Так же очевидно, что ни А, ни В  не равны 4. Тогда кто равен 4? ... ВЫРАЖЕНИЕ. Был получен результат, который просто у нас в уме.

А вот если мы запишем Х=(A+B)/B, тогда мы то, что у нас в уме присвоим Х.

Таким образом, получение некоего результата выражения - это возврат значения этим выражением.

И это возвращенное значение мы присвоили конкретной переменной Х.

А теперь вернемся к Си. Одиночный знак = является оператором присвоения значения возвращенного правым от этого оператора выражением переменной расположенной слева от этого оператора.

Всё. Другого способа присвоения в Си нет. Только через одиночный знак =.

Обратное так же справедливо - если вы где то написали одиночное =, значит вы произвели присвоение. Все остальные арифметические и логические операции способны только возвращать значение.

Физически - возврат значения - это получение результата выражения в некоем временном регистре. Обычно регистре общего назначения (РОН). РОНы отличаются от остальной памяти тем, что доступ к ним не требует занятия шины данных/адреса ОЗУ. Потому что РОНы - это часть арифметико-логического устройства процессора. Так называемая СВЕРХОПЕРАТИВНАЯ память - СОЗУ. При обращении к РОНам адрес РОНа очень короткий (3...5  бит) и содержится прямо за кодом операции инструкции процессора.

Edited by my504

Share this post


Link to post
Share on other sites

LED-драйверы LCM - бюджетное решение для умного дома!

Для более простого и бюджетного решения по организации управляемого освещения в здании с имеющейся системой KNX компания Mean Well предлагает готовые к использованию LED-драйверы семейства LCM/KN, управляемые по протоколу KNX. По своим техническим возможностям эти изделия похожи на драйверы из популярного семейства LCM/(DA).

Подробнее

Только что, my504 сказал:

Попробую зайти с другого конца. Пока забудьте о программировании и Си.

:umnik2::shok::i-m_so_happy:

 

2 минуты назад, my504 сказал:

 теперь вернемся к Си.

Я не понимаю в СИ ...Но @my504 обяснил так что аж захотелось понимать )))

Share this post


Link to post
Share on other sites
11 часов назад, ARV сказал:

Не пойму, в чем вы видите издевательство: я предельно просто (насколько могу) объясняю эти самые азы

Там по моему надо начинать с объяснения необходимости использования букв (вместо цифр) в математических выражениях, поэтому то что вы объясняете это далеко не азы для данного конкретного специалиста, мне кажется.

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


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites
22 часа назад, ARV сказал:

// где-то в главном цикле вы проверяете кнопку и устанавливаете флаг: if((PIND & (1<<BD5)) == 0) flag = 1;

а как же дребезг?

ISR(TIMER1_COMPA_vect)
{
if(button==1) //если нажата кнопка 
    {
    if(f_button==0) //проверяем была ли она нажата ранее, это флаг кнопки
        {
        f_button=1;//если нажато не было то ставим флаг 
        PCTL2 = (1<<PRUN2);//запускаем шим
        while(OCR1A<200) //плавный запуск будет до 200 (частоту нужно подсчитать)
        {OCR1A=OCR1A+5;}
      if(f_button==1)//если кнопка была нажата ранее 
          {
          f_button=0;//снимаем флаг              
          while(OCR1A) //останавливаем пока OCR1A не упадет до нуля
          {OCR1A=OCR1A-5;}
          PCTL2 &=~ (1<<PRUN2);//останавливаем шим
          }
    }
  }

ну у мня почти тоже самое

Share this post


Link to post
Share on other sites
Только что, Дмитрий Вас сказал:

ну у мня почти тоже самое

Даже и близко не то. У вас нет разделения на задачу, решаемую по прерываниям, т.е. частями периодически, и задачу, решаемую последовательно, т.е. "непрерывно". Вы зачем-то то включаете, то выключаете ШИМ... Вопрос: зачем? Я не исключаю, что могут быть причины... но хотелось бы знать. Я просто помню, как я пытался объяснить вам, как модулировать ШИМ синусом... И, не смотря на мои объяснения, вы все равно сделали по-своему, с большим количеством бессмысленных действий.

Только что, Дмитрий Вас сказал:

а как же дребезг?

Вопрос дребезга я не затраивал.


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

Share this post


Link to post
Share on other sites
Только что, ARV сказал:

большим количеством бессмысленных действий.

подождите может вы меня не полностью поняли. синус генерируется и моделируется и даже меняется частота синуса энкодером. я теперь хочу кнопкой на энкодере включать/выключать с плавным пуском и плавным остановом. 

Share this post


Link to post
Share on other sites
Posted (edited)
5 минут назад, Дмитрий Вас сказал:

вы меня не полностью поняли

Я вас отлично понял, я видел ваш код, генерирующий синус - он рабочий, но избыточный примерно на 80%. Это говорит о том, что вы не понимаете, как он работает, и довольствуетесь тем, что "как-то работает". Так и в этом случае: я вам подробно описал, как должно работать "на словах", привел пример кода - и что я вижу? Снова код с циклами внутри обработчика прерываний! Это работать не будет!

Edited by ARV

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

Share this post


Link to post
Share on other sites
23 часа назад, ARV сказал:

Снова код с циклами внутри обработчика прерываний!

хоть убейте но не нашел почему этого нельзя делать. ну да ладно а если сделать так?

ISR(TIMER1_COMPA_vect)
{
	if(!(PIND&(1<<5))) //если нажата кнопка
	{
		switch(f_button)//изначально f_button=0
		{
			case 0://выполняется это условие т.е. включение
			{
				f_button=1;//если нажато не было то ставим флаг
				PCTL2 = (1<<PRUN2);//запускаем шим
				while(OCR0A<200) //плавный запуск будет до 200 (частоту нужно подсчитать)
				{OCR0A=OCR0A+5;}
			}
			case 1://при повторном нажатии на кнопку f_button уже будет = 0
			{
				f_button=0;//снимаем флаг
				while(OCR0A) //останавливаем пока OCR0A не упадет до нуля
				{OCR0A=OCR0A-5;}
				PCTL2 &=~ (1<<PRUN2);//останавливаем шим
			}
		}
	
    }

 

break; не вставил

Share this post


Link to post
Share on other sites
Только что, Дмитрий Вас сказал:

хоть убейте но не нашел почему этого нельзя делать

Еще раз: цикл while не завершится, пока не обнулит OCR1A. Изменение этого регистра он будет делать примерно со скоростью несколько дестков тысяч вычитаний в секунду. Таким образом, когда вам надо будет "плавно" изменить регистр, ваш код изменит его за сотую долю секунды, что ббудет вно "мгновенно", а не "плавно". 

Делать можно вообще все, даже молотком по пальцам бить, но всегда надо завать себе вопрос: это то самое, что я хочу?

Есть и другие проблемы в вашем коде. Например, while(OCR0A<200) {OCR0A=OCR0A+5;} будет вообще "корректно" работать только для исходнх значений OCR1A, кратных пяти. Стоит начать этот цикл при значении OCR1A, например, 254, и вы получите такую цветомузыку... ПОнимаете, почему?

Есть и другие проблемы в вашем коде. Например, while(OCR0A<200) {OCR0A=OCR0A+5;} будет вообще "корректно" работать только для исходнх значений OCR1A, кратных пяти. Стоит начать этот цикл при значении OCR1A, например, 254, и вы получите такую цветомузыку... ПОнимаете, почему?


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

Share this post


Link to post
Share on other sites
1 час назад, Дмитрий Вас сказал:

даже если он записан в обработчике?

Вход в обработчик происходит по сбросу таймера. Скорость выполнения в обработчике ничем не отличается от скорости основного цикла. Программа входит в обработчик и выполняет код в обработчике пока его не завершит. Если обработчик не будет завершен до следующего прерывания таймера, то прерывание будет исполнено сразу после выхода из текущего обработчика.

Share this post


Link to post
Share on other sites

у меня таймер 0 генерирует синус, а 1й проверяет энкодер. что если я в первом буду проверять кнопку типа  if(!(PIND&(1<<5)) {f_button^=0;} меняем флаг на противоположный. а в таймере 0 уже if(f_button&&OCR0A) {OCR0A--;} else.... не придумал еще как наращивать при запуске

Share this post


Link to post
Share on other sites
1 hour ago, Дмитрий Вас said:

1й проверяет энкодер

Я бы сделал вот так: добавил бы два флага go_up и go_down для указания процесса "плавно вверх" и "плавно вниз". В прерывании таймера 1 не спеша бы проверял флаги и нажатие кнопки.

ISR(TIMER1_COMPA_vect)
{
    if(go_up)
    {
        if(OCR0A < 200) //плавный запуск будет до 200 (частоту нужно подсчитать)
            OCR0A = OCR0A + 5;
        else
        {
            go_up = 0; //  останавливаем плавно вверх
            OCR0A = 200; // включено на полную катушку
        }
    }
    else
    if(go_down)    
    {
        if(OCR0A > 5) //останавливаем пока OCR0A не упадет до нуля
            OCR0A = OCR0A - 5;
        else
        {
            go_down = 0; // останавливаем плавно вниз
            OCR0A = 0;   // полностью выключено
        }
    }

    if(!(PIND&(1<<5))) //если нажата кнопка
    {
        if(OCR0A == 0) // было выключено, плавно включаем
            go_up = 1;

        if(OCR0A == 200) // было включено, начинаем плавно выключать 
            go_down = 1;
    }
}

 

Share this post


Link to post
Share on other sites

#include <stdio.h>

if(!(pind5==1))
{
    f_button ^=0;//флаг станет единицей
}
if(f_button==0)//проверка для старта
    {
        OCR0A ++;
    }
   
else//проверка для стоп
    {
        if(OCR0A)//если OCR0A имеет любое значение больше нуля
        {
            OCR0A --;
        }
        if(OCR0A ==0)//если OCR0A достиг нуля
        {
            f_button =0;//сбрасываем флаг
        }
       
    }

int main() {
    return 0;
}

Вот набросал, должно работать. Но остались вопросы. Если я пишу f_button^=0; это придаст первоначальное значение  ноль которое потом поменяет на 1? Или нужно uchar f_button=0; 

 И второй вопрос как бы OCR0A ++; увеличивалось бы только до 200, а потом можно было её менять энкодером?

П.с. код будет в обработчика ISR дабы избежать дребезга

Share this post


Link to post
Share on other sites
Posted (edited)
1 час назад, Дмитрий Мамедиев сказал:

Вот набросал, должно работать

Это вряд ли.

1 час назад, Дмитрий Мамедиев сказал:

Если я пишу f_button^=0; это придаст первоначальное значение  ноль которое потом поменяет на 1?

То, что вы написали, вообще никак не поменяет f_button. Вообще никогда никак.

1 час назад, Дмитрий Мамедиев сказал:

if(!(pind5==1))

Ну и тут какое-то внутреннее сомнение в правильности написанного... Прямо вот утверждать, что это не заработает, не видя, что такое pind5, не могу, но червячок сомнения гложет...

1 час назад, Дмитрий Мамедиев сказал:

int main() {
    return 0;
}

А и после этого надеяться, что будет работать хоть как-то, вообще бесполезно...

Edited by ARV

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

Share this post


Link to post
Share on other sites
16 часов назад, ARV сказал:

А и после этого надеяться, что будет работать хоть как-то, вообще бесполезно...

А я предупреждал ! :)


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites
45 минут назад, ruhi сказал:

предупреждал

Вы предупреждали в отношении совсем другого начинающего. Так что не факт, что ваше возмущение уместно.


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

Share this post


Link to post
Share on other sites
11 часов назад, ARV сказал:

Так что не факт, что ваше возмущение уместно.

Да где ж я возмущался то?

Вот согласитесь, посмотреть как работает операция:

 f_button^=0; это придаст первоначальное значение  ноль которое потом поменяет на 1

лучше всего в консольном С-приложении на компе, для начала, там же можно походить в дебаге - посмотреть значения переменных хочешь в десятичном виде- хочешь в хексе (прежде чем в контроллеры лезть)?

Ну это же глупо (по моему) на форумах выяснять?


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites
Posted (edited)

Здравствуйте! Подскажите мне пожалуйста, как собрать микросхему АЦП в Proteus? Я тут написал код 

//Atmega8
//Укажем частоту
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>
//Инициализируем библиотеку для работы с дисплеем
#include "n5110.h"
#include <stdlib.h>

//Предварительные настройки
void presets(){
//Инициализируем дисплей
    Lcd_init();
//Настройки АЦП
//ADCSRA
ADCSRA |= (1<<ADEN) //Задействовать АЦП
| (1<<ADPS2) | (1<<ADPS2) | (1<<ADPS2) ; //Делитель 128 = 64 кГц

//ADMUX	
ADMUX |= (1<<REFS1)|(1<<REFS0) //Опорное напряжение 2.56 В внутреннее
| (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (1<<MUX0); //Выбор вывода
}

int readADC(){
    ADCSRA |= (1<<ADCSRA); //Запуск преобразования	
	while ((ADCSRA &(1<<ADSC))); //Ожидание окончания преобразования
	return ADC;
}


int main(void)
{
    presets();
    while (1) 
    {
		Lcd_clear();
		char buff[5];
		itoa(readADC(), buff, 10);
		Lcd_print(0,1, FONT_1X, (unsigned char*)buff);
		Lcd_update();
		_delay_ms(200);
		
		
		
    }
}

 набросал схему и почему-то у меня показывает 0

New Project.pdsprj GccApplication7.hex n5110.c n5110.h

Edited by Андрей Протаскин

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Сообщения

  • Similar Content

    • By Alan247
      Представляю на ваш суд:    https://thisismyhobby.ru/AVR_PAL_W.php   Ваше мнение?
       

    • By Rad TV
      Скетч простой и кислий. Сделан автором RadTV канал:https://www.youtube.com/channel/UC1k5elIKErFnmwTzIsRgQrA?view_as=subscriber
      Буду рад рокомендациях и помощи!Сделал сам проект должен бить простим и  что би влезло в ATtini85!
      Есть защита акб и просто парения (!!!Кнопка на розмикания!!!)
      Обновления будут!!!!
       
       
      RadMOD ver1.0.txt
    • By Стас73
      Доброй ночи, уважаемые.
      Прошу Вашего совета по следующей куче проблем для меня, т.к. не соображаю в электронике, схемах, резисторах и подобному, но дружу с компом и есть желание сделать определенный механизм, но пока нет наставления на путь истинный от специалистов)
      Задача состоит в следующем - хочу мотор стеклоочистителя подключить к Ардуино, но управлять им необходимо с кнопки. Шилд, например, который обрабатывает сигнал нажатия на кнопку (допустим кнопка записи), при ее активации, нажимаю на другую кнопку, которая дает команду движку вращаться по часовой стрелке. Отпускают ее, моторчик останавливается. Другая кнопка, вращение в противоположную сторону. Т.е. записал последовательность и продолжительность вращений,  нажимаю вновь на кнопку запись и мои действия сохраняются. Далее на 4 кнопку жму и моя игра с моторчиком автоматически воспроизводится. Если такое выполнимо с помощью плат и шилдов без доп программирования логики, то буду ОЧЕНЬ  признателен если расскажете как вкратце это осуществить или кинете ссылки к примеру на Али с нужными товарами. Если легковыполнимо, то в будущем наверное уже разберусь,  как обойтись без нажатия на 4 кнопку (воспроизведения записанных действий) и запускать этот процесс, подключив датчик движения или звука.
      Если необходимо описывать логику или создавать типа какого-то протокола, что шилд (?) умел понимать, что я от него хочу, то подскажите среду разработки для неба, что б там по минимуму было наворотов) В принципе с основами c++ для Ардуино скорее всего придется ознакомиться. 
      Заранее спасибо!
    • By Ilya Gray
      Доброго времени суток!
      В целом, имеется опыт разработки малых устройств, что-то понимаю, в общем, старательно читаю даташиты, даже понимаю их, но на звание серьёзного инженера (пока что) не претендую.
      Я пытаюсь использовать I2C на 8-битном PIC16F18326. Сижу в даташитах. Всё понимаю, всё делаю, на мой неопытный взгляд, правильно. Даже копирую полностью рабочие примеры (я даже купил такой же микроконтроллер, как в примере, скопировал код, контролируя, что он делает. Но всё равно не работает - SCL/SDA на 5в и всё тут).
      Так вот: PIC16F18326 on breadboard (прошу прощения, я хз как это по-русски) на внутреннем 32мгц кристалле. Чип пашет, без проблем моргаю LEDкой. Ну, думаю, щас быстренько подниму I2C. В итоге SCL SDA сидят на 5в без движения. Я использую LED для отладки. Судя по LED, код заloopливается в месте, где проверяется while PIR1bits.SSP1IF==0. Я уже везде был, кучу форумов перерыл. Уже попробовал всё, что мог представить. Я довольно новый в мире PIC, хотел попробовать их, а они ужасно сопротивляются. Уже 2 недели долблюсь безуспешно.
      Подтяжки 10к, проблем с ними никогда не было.
      Собственно, вот код (я уже там попробовал повыключать ADC, вычитал про баг, что сначала I2C пины надо делать OUTPUT LOW, а потом уже INPUT из-за бага MSSP, но ничего не помогло).
      // PIC16F18326 Configuration Bit Settings // 'C' source line config statements // CONFIG1 #pragma config FEXTOSC = OFF // FEXTOSC External Oscillator mode Selection bits (Oscillator not enabled) #pragma config RSTOSC = HFINT32 // Power-up default value for COSC bits (HFINTOSC with 2x PLL (32MHz)) #pragma config CLKOUTEN = OFF // Clock Out Enable bit (CLKOUT function is disabled; I/O or oscillator function on OSC2) #pragma config CSWEN = ON // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed) #pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled) // CONFIG2 #pragma config MCLRE = ON // Master Clear Enable bit (MCLR/VPP pin function is MCLR; Weak pull-up enabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config WDTE = OFF // Watchdog Timer Enable bits (WDT disabled; SWDTEN is ignored) #pragma config LPBOREN = OFF // Low-power BOR enable bit (ULPBOR disabled) #pragma config BOREN = ON // Brown-out Reset Enable bits (Brown-out Reset enabled, SBOREN bit ignored) #pragma config BORV = LOW // Brown-out Reset Voltage selection bit (Brown-out voltage (Vbor) set to 2.45V) #pragma config PPS1WAY = ON // PPSLOCK bit One-Way Set Enable bit (The PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle) #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a Reset) #pragma config DEBUG = OFF // Debugger enable bit (Background debugger disabled) // CONFIG3 #pragma config WRT = OFF // User NVM self-write protection bits (Write protection off) #pragma config LVP = ON // Low Voltage Programming Enable bit (Low Voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored.) // CONFIG4 #pragma config CP = OFF // User NVM Program Memory Code Protection bit (User NVM code protection disabled) #pragma config CPD = OFF // Data NVM Memory Code Protection bit (Data NVM code protection disabled) // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. #include <xc.h> #include <htc.h> #include <stdio.h> #include <stdint.h> #define _XTAL_FREQ 32000000 void i2c_is_idle(void){ //while(!PIR1bits.SSP1IF); //while(SSPCON2bits.SEN==1 || SSPCON2bits.RSEN==1 || SSPCON2bits.PEN==1 || SSPCON2bits.RCEN==1 || SSPCON2bits.ACKEN==1 || SSPSTATbits.R_nW==1){}; while(PIR1bits.SSP1IF == 0){ PORTCbits.RC2=1; }; // SSP1IF is set when operation complete PORTCbits.RC2=0; PIR1bits.SSP1IF = 0; // clear interrupt flag } void i2c_start(void){ i2c_is_idle(); SSPCON2bits.SEN = 1; } void i2c_rep_start(void){ i2c_is_idle(); SSPCON2bits.RSEN = 1; } void i2c_stop(void){ i2c_is_idle(); SSPCON2bits.PEN = 1; } void i2c_write(uint8_t i2c_data){ i2c_is_idle(); SSPBUF = i2c_data; while(SSPSTATbits.BF != 0); while(SSPCON2bits.ACKSTAT != 0); } uint8_t i2c_read(uint8_t ack){ uint8_t recieve =0; i2c_is_idle(); SSPCON2bits.RCEN = 1; while(SSPSTATbits.BF != 1); recieve = SSPBUF; SSPCON2bits.ACKEN = ack; return recieve; } void i2c_init(void){ TRISCbits.TRISC0 = 1; TRISCbits.TRISC1 = 1; SSPSTATbits.SMP = 1; SSPSTATbits.CKE = 0; SSPCONbits.SSPM = 0x08; SSPADD = 79; SSPCONbits.SSPEN = 1; } void main(void) { ANSELCbits.ANSC0 = 0; //ADC RC0 OFF ANSELCbits.ANSC1 = 0; //ADC RC1 OFF TRISCbits.TRISC2=0; //LED PIN TRISCbits.TRISC0=0; //MSSP bug counter TRISCbits.TRISC1=0; //MSSP bug counter //__delay_ms(5); LATCbits.LATC1=0; //MSSP bug counter LATCbits.LATC0=0; //MSSP bug counter //__delay_ms(5); INTCONbits.GIE=1; //global interrupt en INTCONbits.PEIE=1; //peripheral interrupt en ADCON0bits.ADON=0; //unpower adc just in case i2c_init(); //THIS SETS TRISC BITS FOR SCL SDA while(1){ i2c_start(); i2c_write(0x3C); i2c_stop(); } return; } Задача: просто увидеть коммуникацию на SCL SDA, я уже потом по даташитам таргет девайсов без проблем напишу дрова. Не получается именно осуществлять коммуникацию.
      Подскажите, пожалуйста, я не понимаю, где я дурак, а между тем волос на голове становится всё меньше, а те, что остались, стремительно приобретают серый окрас, ибо 2 недели я долбаюсь с одной проблемой. Благодарю за ваши советы. Спасибо.
       
    • By MirVsem
      Добрый день.
      Есть интересные модули ибп для слаботочки до 1А.
      m.aliexpress.ru/item/4000109380893.html
       По цене идеально подходит для зоопарка роутеров, IoT устройств... Переключение на резерв (туда-обратно) без просадки. Зарядка литиевой банки как положено, всякие защиты от перегрузки и прочее. Казалось бы все замечательно. 
      НО как всегда не без ложки дёгтя.
       Защита от переразрядки работает неадекватно. Хотя возможно это не сама защита, а повышающий модуль. На пороге ~3в у него срабатывает циклический перезапуск и так пока банка не просядет ниже 3в. Точно померять нечем.
      Из наблюдений. Проверил напряжение переключается с 12в на 9в и щелчки. Естественно нагрузка в это время дико насилуется (роутер свистит минут 5 пока полностю не отключится)
      Вопрос к гуру. Возможно ли что-то доработать в даном модуле чтобы исправить этот досадный баг?
×
×
  • Create New...