Поклонники продукции Microchip Technology Inc тусуются тут.
Ответить

Re: Програмирование pic на СИ.

Вт авг 20, 2019 19:52:49

Я рад, что у вас все получилось.

Добавлено after 4 hours 25 minutes 39 seconds:
serg_svd, Дело было в SSPSTAT. Подпилил ваш драйвер ssd1306 под свой i2c, закинул в отладочную плату, красота.
Изображение

Добавлено after 5 minutes 32 seconds:
хотя у меня подтяжка на плате через резисторы 10к к +5 В и все норм работает и раньше работало)

Re: Програмирование pic на СИ.

Ср авг 21, 2019 08:21:32

хотя у меня подтяжка на плате через резисторы 10к к +5 В и все норм работает и раньше работало)

Спасибо за помощь!
У меня тоже резисторы 10кОм были, но я поверх них запаял еще по 10к. В итоге стало 5к подтягивающие. Просто думал в них дело...
Схему на плату ssd1306 я только огрызок нашел, но в ней тоже подтягивающие по питанию после стабилизатора подключены. На своей плате я тщательно все прозвонил. Не думаю, что китайцы столько модификаций плат лепят.
Изображение

Re: Програмирование pic на СИ.

Ср авг 21, 2019 13:28:38

Кстати попробуйте увеличить частоту i2c. Для 128х64 на частоте 100кгц медленный вывод шрифтом 5х8. Чтоб заполнить весь экран символами уходит гдето 0.5 секунды.

Re: Програмирование pic на СИ.

Ср авг 21, 2019 20:38:28

Кстати попробуйте увеличить частоту i2c.

Игрался с частотой. Насколько знаю, предел 400 кГц. Но даже при такой частоте видно, как заполняется дисплей. Для больших объемов выводимой информации я предпочитаю вначале гасить индикатор после очистки, выводить информацию и затем включать его.
PS. я такие дисплеи, хоть и имею несколько штук в наличии, но в своих конструкциях так и не применил. Хотя для простого применнения можно обойтись и без буфера, но, по-хорошему, все-же лучше с буфером. Но для этого требуются жирные контролллеры с минимум 2 кБ памяти.

Re: Програмирование pic на СИ.

Ср авг 21, 2019 21:36:34

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

Re: Програмирование pic на СИ.

Чт сен 19, 2019 16:49:21

Здравствуйте! Нет ли у кого примера динамической индикации на PIC+74HC595 под XC8 компилятор.
На сайте narodstream все хорошо разжёвано, от туда беру примеры, но нет примера именно с 74HC595.
Спасибо.

Re: Програмирование pic на СИ.

Пт сен 20, 2019 21:05:51

расскажите что не получается? толи с пиком не разобрались, или с регистром?
входные пины 595
[10] MR — сброс регистра, при подаче логического нуля на MR и единицы на STCP переводит все выходы в состояние логического нуля;
[11] SH_CP — вход для тактовых импульсов;
[12] ST_CP — линия прерываний;
[13] OE — вход, переводящий выходы из высокоимпедансного состояния в рабочее;
[14] DS — вход данных;
[8] GND — Ground. Земля
[16] VCC — Питание +5 В.

посылка для вывода цифр

. | 0b00000001
0 | 0b00000000
1 | 0b01100000
2 | 0b11011010
3 | 0b11110010
4 | 0b01100110
5 | 0b10110110
6 | 0b10111110
7 | 0b11100000
8 | 0b11111110
9 | 0b11110110

ну а дальше перебор общего у индикаторов как обычно при динамической индикации

Re: Програмирование pic на СИ.

Сб сен 21, 2019 14:24:26

Если я вижу пример, то смогу что то сварганить для своих нужд, с ноля не напишу :facepalm: . Я не настолько знаю С.
Это как читать книгу на английском, имея под рукой словарь.

Re: Програмирование pic на СИ.

Ср дек 11, 2019 01:12:43

На Си писАть не люблю. Там думать надо над языком. Вот на Бейсике - там думать надо именно над "задуманным".
Вложения
PIC12F508Clocks.zip
(1.7 KiB) Скачиваний: 321
PIC12F508Clocks.hex
(2.85 KiB) Скачиваний: 356
Безымянный.JPG
(60.05 KiB) Скачиваний: 452

Re: Програмирование pic на СИ.

Пн янв 20, 2020 20:45:46

Чтобы не создавать отдельную тему, напишу тут:

МК: pic12f683; Программа: MPLAB X IDE; Компилятор: xc8 v2.10(2.05 тоже пробовал)
Проблема: ножка порта сбрасывается на 0 через пару мкс после установления 1.
Код:
Спойлер// PIC12F683 Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = ON // Code Protection bit (Program memory code protection is enabled)
#pragma config CPD = ON // Data Code Protection bit (Data memory code protection is enabled)
#pragma config BOREN = OFF // Brown Out Detect (BOR disabled)
#pragma config IESO = OFF // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF

#include <xc.h>




#define TX GP2
#define RX GP0
#define CODE GP1

unsigned char i=0;
unsigned char RXv;
const char data[255] = { массив из 0,1};

void __interrupt() isr(void) {
if(TMR2IE&&TMR2IF) {
if(!RXv) {
CODE=!data[i];
i++;
}
RX=!RXv;
RXv=!RXv;
TMR2IF=0;
return;
}
if(INTE&&INTF) {
TMR2ON=1;
TMR2IF=0;
TMR2IE=1;
RX=1;
RXv=1;
CODE=1;
}
INTF=0;
return;
}

void main(void) {

// MC CONFIG
OSCCON=0b01110100;
OSCTUNE=0b00001111;

GIE=1; // Global INTERRUPT on
PEIE=1;
INTE=1; // internal INTERRUPT on
INTEDG=1; // Interrupt on rising edge
T2CON=0; //Config TIMER2 PreScealer 1:1 PostScealer 1:1
PR2=90; // TMR2 interrupt, RX frequency
TRISIO=0b00111100; // Set GP2 input GP1 GP0 output
ANSEL=0; //Set ports as digital
WPU=0b111000; //Disabble weak pull ups
while(1) {
if(i==255) {
TMR2IE=0;
i=0;
CODE=0;
RX=0;
RXv=0;
}

}

}

сбрасывается ножка code (gp1) на ножке RX была подобная проблема когда запись была RX=!RX. с вводом переменной RXv все нормализовалось. я решил, что при чтении значения с порта, чтобы сделать инверсию он сбрасывался. но с ножкой CODE такой проблемы нет... она не читается в программе.
Логика программы: по запросу с ТХ (прямоугольный импульс длиной около 50мс) по завершению идёт генерация импульсов синхронизации на RX а на ножке Code идёт пробитовая посылка на каждом пике RX перед спадом.
Осцилограмма работы
Изображение
видно что логика работает 255 бит отправляются, но при передаче 0( т.е. 1 потому что через транзистор) на gp1 он появляется кратковременно и не остаётся в нем, а возвращается в 1( т.е в 0). оранжевым дорисовал как должно быть в начале идут 0 т.е. должна быть прямая. осцилограмма снята на выходе, т.е. после транзисторов. на прямую с мк то же самое только наоборот.
Схема устройства:
Изображение

в чем может быть причина такого поведения? компилятор чудит? осцилятор используется внутренний на 8Mhz, но кроме как что gp4,5 всегда на вход будут ничего не нашёл в этом режиме. или переферия какая сбрасывает на 0??

P.S. пока писал пришла в голову мысль, что может быть это из-за инверсии "!" ?? попробую завтра массив вручную инвертировать, хотя не очень логично т.к. RX=!RXv; проходит нормально...

Re: Програмирование pic на СИ.

Сб янв 25, 2020 06:26:11

Процедура RMW - чтение-модификация-запись.
При записи в любой бит порта читается ВЕСЬ ПОРТ, затем модифицируется этот бит, затем результат записывается в ВЕСЬ ПОРТ. Чтение порта при записи бита В ЭТОМ СЕМЕЙСТВЕ МК происходит прямо с пинов, а не с выходной буферизованной защелки. Если пин сильно нагружен, то на нем может быть напряжение ниже порога единицы и при чтении на нем будет ноль. Таким образом, этот ноль будет перезаписан в этот пин при записи совершенно в другой пин этого порта. Тоже самое происходит, если записи следуют раньше, чем на пине устанавливается уровень, т.е. слишком быстро.
Ворк эрраунд. Держать в коде копию порта и работать с ней, отдавая в порт только его копию целиком, а не побитно.

Re: Програмирование pic на СИ.

Вс фев 09, 2020 20:01:13

Процедура RMW - чтение-модификация-запись.
При записи в любой бит порта читается ВЕСЬ ПОРТ, затем модифицируется этот бит, затем результат записывается в ВЕСЬ ПОРТ. Чтение порта при записи бита В ЭТОМ СЕМЕЙСТВЕ МК происходит прямо с пинов, а не с выходной буферизованной защелки. Если пин сильно нагружен, то на нем может быть напряжение ниже порога единицы и при чтении на нем будет ноль. Таким образом, этот ноль будет перезаписан в этот пин при записи совершенно в другой пин этого порта. Тоже самое происходит, если записи следуют раньше, чем на пине устанавливается уровень, т.е. слишком быстро.
Ворк эрраунд. Держать в коде копию порта и работать с ней, отдавая в порт только его копию целиком, а не побитно.


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

Re: Програмирование pic на СИ.

Ср июл 15, 2020 23:48:26

На Си писАть не люблю. Там думать надо над языком. Вот на Бейсике - там думать надо именно над "задуманным".
-не знаю, как на бейсике, а для паскаля вот разрабатывается транслятор, чтобы отлаживать на дельфях, а потом транслировать в код Си.

Re: Програмирование pic на СИ.

Чт июл 16, 2020 06:57:54

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

Re: Програмирование pic на СИ.

Чт июл 16, 2020 14:20:08

ARV - я думаю, напрямую делать компилятор малоперспективно для маленьких опенсорсных проектов. Т.к. он всё равно будет хуже, чем MPlabX, и как только энтузиасты перестанут его поддерживать, то весь код превратиться в тыкву. А так можно дальше на Си проекты развивать.

Re: Програмирование pic на СИ.

Чт июл 16, 2020 15:28:51

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

Re: Програмирование pic на СИ.

Чт июл 16, 2020 16:15:29

ARV - я думаю...

NStorm писал(а):...обычно мало пригодные для правки человеком. С тем же успехом можно пытаться.....

Даладна!!! :))) :))) :)))
Коллеги, это только мне кажется, что ARV ерничает? Вообще то это был сарказм. И тут можно только поржать, но никак не обсуждать на полном серьезе перспективы.

Re: Програмирование pic на СИ.

Чт июл 16, 2020 19:27:42

КРАМ, а не ARV отвечал, там явный сарказм был. А lin17, который про транслятор из "делфи" писал.

Re: Програмирование pic на СИ.

Вт окт 20, 2020 09:11:52

А как в MPLAB X посмотреть дизасм? Компилятор XC8. Версии MPLAB X и компилятора последние.
Вот только с Ассемблера перешел на СИ, написал работающую программу. Хотелось бы узнать мнение гуру о коде программы. Пойдет такое написание на СИ? Или что-то можно по другому скомпоновать в программе?
Спойлер
Код:
while (1)
{
PWM1CON = 0b00000000;           // отключаем ШИМ1
FVRCON = 0b00000000;            // отключаем ИОН, отключаем температурный индикатор
ADCON = 0b00000000;             // отключаем модуль АЦП
PORTA = 0;                      // все выходы порта переводим в низкое состояние
__delay_ms(500);
IOCIE = 1;                      // разрешаем прерывание по изменению уровня PORTA
IOCAF = 0;                      // сбрасываем флаг IOCAF (свидетельствующий о прерывании RA3)
SWDTEN = 0;                     // отключаем сторожевой таймер на период сна
SLEEP();                        // здоровый крепкий сон до пробуждения нажатием кнопки)
IOCIE = 0;                      // запрет прерывания по изменению уровня PORTA
SWDTEN = 1;                     // включаем сторожевой таймер
   
     CLRWDT();
     LED = 1;                   // включаем питание
     PWM1CON = 0b11000000;      // вкл ШИМ для двухтонального сигнала включения
     TMR2 = 0;                  // сброс TMR2 для исключения пауз между тонами
     PR2 = 10;                  // первый тон сигнала включения ~ 700 Гц
     PWM1DCH = 5;               // -//-
     __delay_ms(111);
     TMR2 = 0;                  // сброс TMR2 для исключения пауз между тонами
     PR2 = 6;                   // второй тон сигнала включения ~ 1,1 кГц
     PWM1DCH = 3;               // -//-
     __delay_ms(111);
     PWM1CON = 0b01000000;      // выкл ШИМ
     FVRCON = 0b10000001;       // включаем ИОН 1,024V, отключаем температурный индикатор
     ADCON = 0b00011101;        // включаем модуль АЦП, FVR вход (фиксированное опорное напряжение), FOSC/2
 
       GO:
       for(n=0; n<=15000; n++)  // время работы основного цикла программы, где 1000n соответствует ~ 1 минуте работы (максимальный n=65535, ТЕ 65мин)
       {
       if (!TK1)                // если перемычка на 0, то бесконечный режим работы (без таймера))
         {
         n=0;
         }
       CLRWDT();
       __delay_ms(52);
       if (!TK)                 // если кнопка нажата - подаем короткий звуковой сигнал
          {
          PWM1EN = 1;           // вкл ШИМ звукового сигнала нажатия кнопки
          __delay_ms(55);
          PWM1EN = 0;
          __delay_ms(999); 
          if (!TK)              // если кнопка нажата более 1 сек - отключаем питание
            {
            goto Power_OFF;
            }
            else                // если кнопка нажата менее 1 сек - обнуляем таймер ожидания
            {
            goto GO;
            }       
          }
       
       GO_nDONE = 1;            //начать преобразование АЦП
       while(GO_nDONE);         //ожидание окончания преобразования АЦП
       if(ADRES > 86)           //если U ниже 3.0В выключаем питание
                {
                goto Power_OFF;
                }
                else
                  {
                  if(ADRES > 80) //если U ниже 3.3В включим двойной предупредительный звуковой сигнал о низком заряде АКБ, который повторяется каждые 15с
                    {
                      if (i<2)
                      {
                      PWM1EN = 1;       // вкл ШИМ для предупредительного звукового сигнала
                       __delay_ms(55);
                      PWM1EN = 0;       // выкл ШИМ
                       __delay_ms(33);
                      }
                      i++;
                    }
                  }
       if(n==14000)                     // вкл предупредительный 4-хкратный звуковой сигнал, предупреждающий о отключении питания, где 1000n соответствует ~ 1 минуте работы (максимальный n=65535, ТЕ 65мин)
          {
           for(m=0; m<=3; m++)
             {
             PWM1EN = 1;                // вкл ШИМ для предупредительного звукового сигнала
             __delay_ms(155);
             PWM1EN = 0;                // выкл ШИМ
             __delay_ms(77);   
             }
          }
        }
 
     Power_OFF:
     PWM1EN = 1;                // вкл ШИМ для двухтонального сигнала выключения
     TMR2 = 0;                  // сброс TMR2 для исключения пауз между тонами
     PR2 = 6;                   // первый тон ~ 1,1 кГц
     PWM1DCH = 3;               // -//-
     __delay_ms(111);
     TMR2 = 0;                  // сброс TMR2 для исключения пауз между тонами
     PR2 = 10;                  // второй тон ~ 700 Гц
     PWM1DCH = 5;               // -//-
     __delay_ms(111);
     PWM1EN = 0;                // выкл ШИМ
     LED = 0;                   // отключаем питание
}
     return;

}

Re: Програмирование pic на СИ.

Вт окт 20, 2020 11:29:23

А как в MPLAB X посмотреть дизасм? Компилятор XC8. Версии MPLAB X и компилятора последние.

Включить отладку (можно через симулятор), потом Window->Debugging->Disassembly

Добавлено after 25 minutes 22 seconds:
4uvak, напишите модель МК для кода, так проверить удобнее будет собрав исходник.

Добавлено after 2 minutes 56 seconds:
Вообще конечно видно, что переход был с асма ) Стилистика осталась в асм стиле. Вместо меток лучше в виде функций оформить. Да и вообще в Си метки почти никогда не нужны.

Добавлено after 23 minutes 7 seconds:
Чисто в плане избавления от ненужных меток:
Спойлер
Код:
void init() {
    PWM1CON = 0b00000000; // отключаем ШИМ1
    FVRCON = 0b00000000; // отключаем ИОН, отключаем температурный индикатор
    ADCON = 0b00000000; // отключаем модуль АЦП
    PORTA = 0; // все выходы порта переводим в низкое состояние
    __delay_ms(500);
    IOCIE = 1; // разрешаем прерывание по изменению уровня PORTA
    IOCAF = 0; // сбрасываем флаг IOCAF (свидетельствующий о прерывании RA3)
    SWDTEN = 0; // отключаем сторожевой таймер на период сна
    SLEEP(); // здоровый крепкий сон до пробуждения нажатием кнопки)
    IOCIE = 0; // запрет прерывания по изменению уровня PORTA
    SWDTEN = 1; // включаем сторожевой таймер
}

void power_on() {
    LED = 1; // включаем питание
    PWM1CON = 0b11000000; // вкл ШИМ для двухтонального сигнала включения
    TMR2 = 0; // сброс TMR2 для исключения пауз между тонами
    PR2 = 10; // первый тон сигнала включения ~ 700 Гц
    PWM1DCH = 5; // -//-
    __delay_ms(111);
    TMR2 = 0; // сброс TMR2 для исключения пауз между тонами
    PR2 = 6; // второй тон сигнала включения ~ 1,1 кГц
    PWM1DCH = 3; // -//-
    __delay_ms(111);
    PWM1CON = 0b01000000; // выкл ШИМ
    FVRCON = 0b10000001; // включаем ИОН 1,024V, отключаем температурный индикатор
    ADCON = 0b00011101; // включаем модуль АЦП, FVR вход (фиксированное опорное напряжение), FOSC/2

}

void power_off() {
    PWM1EN = 1; // вкл ШИМ для двухтонального сигнала выключения
    TMR2 = 0; // сброс TMR2 для исключения пауз между тонами
    PR2 = 6; // первый тон ~ 1,1 кГц
    PWM1DCH = 3; // -//-
    __delay_ms(111);
    TMR2 = 0; // сброс TMR2 для исключения пауз между тонами
    PR2 = 10; // второй тон ~ 700 Гц
    PWM1DCH = 5; // -//-
    __delay_ms(111);
    PWM1EN = 0; // выкл ШИМ
    LED = 0; // отключаем питание
}

void main(void) {
    init();
    power_on();
    CLRWDT();
    while (1) {
        for (n = 0; n <= 15000; n++) // время работы основного цикла программы, где 1000n соответствует ~ 1 минуте работы (максимальный n=65535, ТЕ 65мин)
        {
            if (!TK1) // если перемычка на 0, то бесконечный режим работы (без таймера))
            {
                n = 0;
            }
            CLRWDT();
            __delay_ms(52);
            if (!TK) // если кнопка нажата - подаем короткий звуковой сигнал
            {
                PWM1EN = 1; // вкл ШИМ звукового сигнала нажатия кнопки
                __delay_ms(55);
                PWM1EN = 0;
                __delay_ms(999);
                if (!TK) // если кнопка нажата более 1 сек - отключаем питание
                {
                    power_off();
                    return;
                } else // если кнопка нажата менее 1 сек - обнуляем таймер ожидания
                {
                    break;
                }
            }

            GO_nDONE = 1; //начать преобразование АЦП
            while (GO_nDONE); //ожидание окончания преобразования АЦП
            if (ADRES > 86) //если U ниже 3.0В выключаем питание
            {
                power_off();
                return;
            } else {
                if (ADRES > 80) //если U ниже 3.3В включим двойной предупредительный звуковой сигнал о низком заряде АКБ, который повторяется каждые 15с
                {
                    if (i < 2) {
                        PWM1EN = 1; // вкл ШИМ для предупредительного звукового сигнала
                        __delay_ms(55);
                        PWM1EN = 0; // выкл ШИМ
                        __delay_ms(33);
                    }
                    i++;
                }
            }
            if (n == 14000) // вкл предупредительный 4-хкратный звуковой сигнал, предупреждающий о отключении питания, где 1000n соответствует ~ 1 минуте работы (максимальный n=65535, ТЕ 65мин)
            {
                for (m = 0; m <= 3; m++) {
                    PWM1EN = 1; // вкл ШИМ для предупредительного звукового сигнала
                    __delay_ms(155);
                    PWM1EN = 0; // выкл ШИМ
                    __delay_ms(77);
                }
            }
        }
        return;
    }
}

Что еще я бы улучшил, но уже безотносительно перехода с асма:
1. Мне не нравится сброс n каждый раз в случае перемычки. Обычно перемычку на работающем ус-ве не меняют. Поэтому обычно значение перемычки считается только один раз. А дальше я бы просто сделал бы бесконечный цикл, где n приращивалось бы или нет.
2. Нажатие кнопки проверяется разово. При этом ожидание и замеры АЦП останавливаются. Дребезгом или дрочением кнопки можно тормознуть выполнение другого участка кода.
3. Вместо перехода на конец программы, где просто будет бесконечный цикл ничего не делания крутится, я бы в конце power_off() в спящий режим бы уходил бы постоянный.
Последний раз редактировалось NStorm Вт окт 20, 2020 13:47:05, всего редактировалось 1 раз.
Ответить