PIC Лаборатория

PIC16 PIC18
*Hi-tech PICC compiler 9.71a *XC8
Эксперимент #1: Мигаем светодиодом.  Эксперимент #1: Usart.
Эксперимент #2: Подключаем кнопку.  Эксперимент #2: DHT22.
Эксперимент #3: Таймер TMR0.  Эксперимент #3: ADC
Эксперимент #4: Подключение семисегментного дисплея через сдвиговый регистр.  Эксперимент #4: Энкодер
Эксперимент #5: Использование прерываний.
Эксперимент #6: ЖК дисплей 16х2.
Эксперимент #7: Использование компаратора.
Эксперимент #8: Таймер TMR1.
Эксперимент #9: Таймер TMR2.
Эксперимент #10: Модуль CCP(Capture/Compare).
Эксперимент #11: Модуль ШИМ(PWM).
Эксперимент #12: Внутренняя EEPROM.
Эксперимент #13: Программный I2C.
Эксперимент #14: USART(UART).
Эксперимент #15: Часы реального времени DS1307.
Эксперимент #16: 1-wire и датчик DS18b20.
Эксперимент #17: Часы+термометр два в одном.
Эксперимент #18: Win приложение для работы с COM портом (Borland C++ Builder).
Эксперимент #19: Win приложение для работы с COM портом (Qt).
Эксперимент #20: Энкодер.
Эксперимент #20.1: Управление энкодером методом опроса состояний.
Эксперимент #21: ИК управление протокол RC5.
Эксперимент #22: POR, BOR, etc.
Эксперимент #23: Сохранение настроек в EEPROM при сбросе питания
Эксперимент #24: Датчик влажности DHT11
Эксперимент #25: Ультразвуковой модуль измерения расстояния HC-SR04
Эксперимент #26: Использование графического дисплея на контроллере SBN1661G (SED1520).

PIC Лаборатория: 29 комментариев

  1. Наверное единственный ресурс где всё разжёвано по PIC16.
    Скажу сразу – получилось не всё, пробовал погонять в PROTEUS’е, но ШИМ там почему то не запустился.

    Ответить

  2. Прошу прощения – поставил осциллограф и увидел импульсы. Вот только размах импульсов почему то 500 мВ. Цифровой анализатор такие уровни не видит.
    Так что всё в порядке, Proteus тоже рулит! ))

    Ответить

  3. Ну правильно, потому что у вас скорее всего щупы с делителем 10:1. Таким образом реальная амплитуда равна 500мВ*10 = 5 В.

    Ответить

  4. Статьи супер!
    Вот только было бы вообще классно еслиб была указана конкретная версия компилятора, и какая версия Стандарт или Про. У меня ни один проект в котором используются __delay_ms(xx) так и не скомпилировался…. :((((

    Ответить

  5. Компилятор Hi-tech PICC compiler pro 9.71a. Посмотрите мануал на ваш компилятор по поводу использования в нем этого макроса, либо давайте ваш email и я скину вам свой компилятор.

    Ответить

  6. Огромное спасибо Автору! Как-то давно писал программу для 16ф84 на ассемблере, теперь понадобилось снова, решил на 16ф628 сделать устройство и на Си программу, тем более что опыт программирования на Си под дос был. Не было только разжеванного мануала, как для ассемблера. Тут я нашел все необходимое. И I2C, когда-то освоенные на ассемблере, и требуемый сейчас 1-провод, и ШИМ(в симуляторе MPLAB элментарно запустился, только не сразу, а после переполнения таймера :) ) и много чего полезного. Доступно и понятно(ну кто уже связывался с Си, МК). Спасибо еще раз.

    Ответить

  7. Привет админ! На контроллерах можно всякой интересной всячины творить!
    Только не пойму язык, на котором вы программируете. Если на С – впишите название хорошего учебника, заточенного под PIC.

    У тебя же копии ответа на коммент на мыло отсылаются? :) Если нет и если не трудно – на почту ответь.

    А так благодарю за проявленный интерес к аудитории! :)

    Ответить

  8. Язык С, компилятор написан прямо на этой странице вверху.
    Про учебник тоже ничего не посоветую, т.к. сам учился по всяким quick starts и по примерам программ с забугорных сайтов, а учебника по pic микроконтроллерам для себя я толкового и не нашел, мне они все показались излишне затянутыми и перегруженными (за исключением небольшого мануала от mikroelektronika).

    PS. Для себя я давно понял, что самый быстрый способ научится что-то делать – это подстраиваясь под конкретную задачу искать конкретные статьи и мануалы.

    Ответить

  9. Эксперимент 24 исчез, если не ошибаюсь- датчик влажности. Сайт хороший, продолжайте. Успехов.

    Ответить

    sarge Ответил:

    Спасибо, я и не заметил, что он отсюда пропал. Поправил :)

    Ответить

  10. Написать бы вам книгу прямиком со всеми опытами, получится наглядней чем у Шпака. И содержание ооочень емкое и полезное.

    Ответить

    sarge Ответил:

    В книгу видео не вставишь, а это иногда бывает очень полезно :)
    Да и ресурсы/возможности не те.

    Ответить

  11. Да , Шпак отдыхает . Спасибо за ваш труд . Я новичок зеленый совсем .
    Облазил кучу сайтов , но так как здесь нигде не расписано . Да и исходники много где не выкладывают .

    Ответить

    sarge Ответил:

    Спасибо за отзыв!

    Ответить

  12. Уважаемый sarge!
    С вашей подачи начал изучать Си, многое прояснилось и начало получаться. Но вот столкнулся с одной проблемой. В ходе измерения напряжения с помощью АЦП нужно перемножить два числа, результат заведомо больше 65536. Все это происходит в функции обработки результата оцифровки. Так вот, операция умножения в функции обработки вызывает стандартную функцию умножения из файла wmul.c. А эта функция умножения возвращает значение типа unsigned int, естественно, усеченное. Явное указание типа перед произведением ничего не меняет, все равно вызывается функция из файла wmul.c. А вот если разместить операцию умножения чисел не в функции обработки, а непосредственно в main(), то происходит вызов функции умножения уже из файла lmul.c, которая возвращает значение типа unsigned long. Но ведь неудобно все вычисления располагать непосредственно в теле main(), для того и была придумана система функций. Смена компилятора с HI_TECH_Software v9.71 на xc8 ничего не дала, там аналогичные процессы. Можно, конечно, скопировать текст функции умножения нужного формата в отдельную функцию, пристегнуть ее к проекту и везде вместо умножения делать ее вызов. Можно, работает, но крайне неудобно.
    Почему так своевольничают компиляторы? Может, я нарушаю какие-то правила? В ассемблере подобных “фокусов” не встречал. Текст программы прилагаю.
    //==============================================================
    #include

    unsigned int Uref=500; long int Uout; // переменные для АЦП
    long int convDigToU(unsigned int Dig, unsigned int U1); // ф-я преобразования (фрагмент)
    unsigned long multipl(unsigned long mult1,unsigned long mult2);
    // unsigned int – до 65535; long int – до 4 294 967 295

    void
    main(void)
    {
    long int k1,k2; // до 4294967295

    Uout = 0;
    k2 = 132; // начальное значение
    k1=0;

    Uout=k2*500; // здесь вызывается функция умножения unsigned long __lmul()
    // из файла lmul.c, она возвращает результат типа long.
    // результат умножения правильный.

    k1=k2*500;
    Uout=0; k1=0; // сброс

    Uout = convDigToU(k2,Uref); // при k2=132 результат неверный

    Uout = multipl(k2,Uref); // результат правильный.
    }

    // =============================================================
    // функция обработки (фрагмент умножения двух чисел)
    long int
    convDigToU(unsigned int Dig, unsigned int U1)
    {

    long int sd1,sd2;

    sd1 = (long int)(Dig*U1); // тут вызывается ф-я unsigned int __wmul() из wmul.c
    // ее максимальное возвращаемое значение 65535, а результат произведения
    // заведомо больше и функцией урезается. Принудительное назначение типа
    // (long int) не срабатывает.

    sd1 = multipl(Dig,U1); // результат правильный
    return sd1;
    }
    // =============================================================
    // копия стандартной функции умножения из lmul.c
    unsigned long
    multipl(unsigned long multiplier, unsigned long multiplicand)
    {
    unsigned long product = 0;

    do {
    if(multiplier & 1)
    product += multiplicand;
    multiplicand <>= 1;
    } while(multiplier != 0);
    return product;
    }

    Ответить

    sarge Ответил:

    Добрый день,

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

    Вы написали свою функцию, которая работает – замечательно, хотите чтобы она была отдельным файлом – вынесите ее в какойнить mymath.c mymath.h, лично я тут никаких неудобств не вижу.

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

    Ответить

    Paulwasw Ответил:

    Наверное я слишком мудрено сформулировал свою проблему. Попробую попроще. Есть два числа в виде переменных типа int a=500, b=132; Нужно получить их произведение, это уже тип long int c;
    Нужно c = a * b. Если эту операцию выполнять в ф-ии main(), то результат будет 66000. А если то же самое произведение выполнить в функции, аргументы которой int (и a и b не превышают), но которая должна возвращать тип long int (и это объявлено), результат будет 464, т.е. урезан до int. И принудительное приведение типов не помогает. А вот если аргументы функции объявить как long, ее результат будет правильным.
    Почему в первом случае функция понижает результат, хотя ее возвращаемое значение объявлено как long int?

    Ответить

    sarge Ответил:

    Да, у вас было слишком много дополнительной информации, которая на мой взгляд только сбивает с толку – АЦП, конверсии – все это не важные дополнения, я люблю простые вещи, особенно при дебаге.

    Дальше, вы пытаетесь вытянуть у меня знания, которых я в принципе не особо имею, но попытаюсь помочь.

    Действительно, я попробовал набросать код с умножением в мейне и в функции, но у меня везде его урезало до 464 (pic16f628a, hi-tech picc c compiler 9.71), но если сделать приведение типов не так как у вас, а для каждой переменной, то все замечательно отрабатывает:

    #include <stdio.h>;
    #include <htc.h>;
    #define _XTAL_FREQ 4000000
    #include "usart.h";
    
    
    __CONFIG(LVPDIS & WDTDIS & MCLREN & UNPROTECT & HS);
    int a=500, b=132;
    long int c_fun;
    void PrintMultipl(int ain, int bin);
    
    void main(void){
        TRISB4 = 0; TRISB6 = 0; TRISB7 = 0; TRISB5 = 0;
    
    
        init_comms();	// set up the USART - settings defined in usart.h
        printf("Starting...\r\n");
    
        printf(&quot;Hello, World!\n&quot;);
        long int c = (long int)a*(long int)b;
        printf("From main: \r\n");
        printf("%d",c);
        printf("\r\n");
        PrintMultipl(a, b);
    
     while(1){};
    }
    
    
    void PrintMultipl(int ain, int bin)
    {
        c_fun = (long int)ain * (long int)bin;
        printf("From function: \r\n");
        printf("%d",c_fun);
        printf("\r\n");
    }
    

    Результат:

    Обратите внимание, что переменная здесь имеет правильную величину, но в printf она усекается до int.

    P.S. И не спрашивайте почему приведение типов надо делать так, я не смогу дать теоретического обоснования :)

    Ответить

    sarge Ответил:

    Ну и вот тут вроде объясняют почему нельзя перемножить два 16 битных числа в одно 32 битное:
    http://www.microchip.com/forums/m551563.aspx

    Ответить

    Paulwasw Ответил:

    Уважаемый sarge! Большое спасибо за ответ.
    Я еще новичок в Си, читаю книжки и верю всему, что написано. А для PIC16 по ряду вопросов, видимо, есть свои оговорки. В частности, в hi-tech picc c compiler 9.71 аж четыре функции умножения: для unsigned char, для unsigned int, для unsigned short long и для unsigned long (соотв. 1, 2, 3 и 4 байтные). Компилятор анализирует входные аргументы и вызывает соответствующую функцию. И для типа int результат будет только int, не выше. Потому что будет вызван двухбайтный вариант (wmul.c), который возвращает значение int. И заставить ее возвращать long никак не получится. А значение long может вернуть только функция из lmul.c. А чтобы вызвать ее, аргументы д.б. не int, а long, это обязательно. Либо, как вариант – скопировать тело в свою функцию, где сделать нужные определения. Хороший урок, очень полезный. Еще раз спасибо!
    В процессе изучения вопроса столкнулся с типом “unsigned short long” – ни в одном справочнике его не нашел, поиск в Гугле тоже ничего не дал. Он используется в файле tmul.c и в массе других. Как оказалось, это 24-битный формат данных, нечто среднее между int и long. Как я понимаю, очередная особенность от PIC16.

    Ответить

    sarge Ответил:

    Да, возможно очередная особенность…

    Если мой пример был полезен, рад был помочь, чем смог :)

    Ответить

  13. Спасибо за энкодер – все отлично рассказано.
    А есть ли модель мотора с энкодером для протеуса ?

    Ответить

    sarge Ответил:

    Пожалуйста.
    Модели мотора с энкодером я не делал, так что нет.

    Ответить

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">