Эксперимент #1.18 UART в PIC18 XC8

В общем думал я, что все будет по накатанной идти, а оказалось, что в использовании уарта в 18 серии есть некоторые различия.

Компилятор XC8 имеет набор встроенных функций для работы с периферией, найти заголовочные файлы можно в папке /includes/plib. Нас на данный момент интересует usart.h.

Сформулируем интересующие нас задачи:

  • Запись одного символа
  • Запись строки
  • Чтение одного символа = 1 байта
  • Чтение нескольких байт

Все это дело будем пробовать завести на PIC18F14K50.

Сначала я приведу картинки из протеуса, а уже файнал вершн будет в конце на реальной тестовой плате.

Поехали :)

Первым делом нужно как водится настроить уарт. Для этого существует функция OpenUSART(Config, baud), где Config это преднастройка по своему виду похожая на __CONFIG, а baud коэффициент, используемый при расчете бодрейта:

FOSC/[16 (baud+1)]

Попытаемся рассчитать этот коэффициент для бодрейта 9600 и кварца 12 МГц

baud = 12M/(9600*16) – 1 = 77.125 ~ 77

По поводу настроек конфига рекомендую обратиться в файлик pic18_plib.pdf, лежит в директории docs компилятора XC, там все очень подробно и прекрасно расписано.

Начнем с теста записи одного байта, для этого предназначена функция:

void WriteUSART(char data)

Ну вроде как все довольно прозрачно, пора практиковаться:

*Решил обновить подсветку синтаксиса, что-то меня старая начала угнетать :)

Тест:

Дальше надо бы строку научиться пулять :)

Для этих целей есть готовая функция:

void putsUSART( char *data)

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

Ответ на первый вопрос – да, можно вводить любые служебные символы (типа \r\n) все отрабатывается замечательно, с числами сложнее, это не готовая функция printf.

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

Кстати если не применять макрос while(BusyUSART()); есть шанс потерять кучу первых байт.

А теперь попытаемся поэкспериментировать с нашей новой функцией и просто с выводом строки

И то, что получилось:

Вроде как работает, можно двигаться дальше.

Чтение.

Я юзаю pic18f14k50, у которого RB5 аналоговый канал, то есть сначала нужно выключить аналоговые буферы.

ANSEL = 0;
ANSELH = 0;

И можно работать :)

Как обычно есть два пути – через *опу и прерывания, но так как у нас эксперимент, мы пойдем первым путем :)

Считать один байт можно с помощью функции

char ReadUSART(void)

То есть, например, это можно организовать как-то так:

И все, теперь ваш байт из уарта находится в переменной rxbyte. Опять таки нужен первый макрос, иначе регистр не очистится и в терминал постоянно будет сыпаться его содержимое (для случая работы в цикле).

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

void getsUSART(char *buffer, unsigned char len)

Она считает ровно ваши len байт.

Придумать как отобразить работу чтения без видео я как-то не очень смог, так что придется вам показать еще и видео (:

Здесь разместим код, того, что буду показывать:

Ну а здесь уже собственно результат:

Ну и как обычно, исходники можно найти в репе.

Эксперимент #1.18 UART в PIC18 XC8: 15 комментариев

  1. я про готовую библиотеку и не подумал даже, все по минимому:

    SPBRG = 77;//устанавливаем скорость для USART 9600 при 12*4=48Mhz
    RCSTA = 0b10010000;//регистр состояния и управления приемника USART
    TXSTA = 0b00100000;//регистр состояния и управления передатчика USART
    BAUDCON = 0b01000000;

    unsigned char read(void)
    {
    do{;}while(PIR1bits.RCIF == 0);
    return RCREG;
    }

    void write (unsigned char tmp)
    {
    TXREG = tmp; //записываем байт в регистр TXREG
    do{;}while(TXSTAbits.TRMT == 0);//ждем пока в TSR есть данные
    }

    Ответить

    sarge Ответил:

    Я в последнее время люблю все готовое :)

    Для строки то функция где? :)

    Ответить

    electronic255 Ответил:

    в компиляторе 3.46 нельзя выводить строки как обычно, например как у тебя : putsUSART( (char *) “Welcome to Diymicro.ru \r\n” );

    нужно создать массив с символами,а потом выводить его.
    не помню в каком проекте эксперементировал,поэтому и не написал пример.
    на тот момент когда занимался USARTом в PIC18 про XC8 не знал

    Ответить

    sarge Ответил:

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

    Но раз нам все дают готовое прямо в компиляторе, то зачем нам этот гемор? :)

    Ответить

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

    Ответить

  3. а почему ты не использовал внутренний кварц? в PIC18F14K50 есть внутренний на 12MHZ

    Ответить

    sarge Ответил:

    Внутренний RC в смысле?
    Если да так он почти во всех есть, просто у меня привычка чтоли, что если могу заложить получше возможность, то закладываю.

    Ответить

    electronic255 Ответил:

    не 12MHz а 16MHz.не совсем уверен что RC.тот регистр который отвечает за выбор частоты называется OSCILLATOR CONTROL REGISTER,там что то про RC совсем ни слова.
    у данного мк и так портов не много, так еще и пару на кварц отдать надо

    Ответить

  4. Здравствуйте.
    Подскажите пожалуйста #pragma config WDTEN = OFF, LVP = OFF, FOSC = HS
    так биты конфигурации настраиваются в XC8 или же #FUSES? Или и так, и так можно?
    Что-то на __CONFIG у меня просто ругается…..
    ПРичем если я так напишу, то при запуски проекта в более старой версии MPLAB (не X), то это будет выводиться ошибкой и там только через __CONFIG надо будет, т.к. компилятор хайтековский, а не XC8?

    Ответить

    sarge Ответил:

    #pragma config – XC8
    __CONFIG – hi-tech PICC compiler

    Читаем мануал на XC8 и видим:

    The 8-bit compilers have used the __CONFIG() macro for some targets that did not
    already have support for the #pragma config.
    For the 8-bit compilers, change any occurrence of the __CONFIG() macro, such as
    __CONFIG(WDTEN & XT & DPROT)
    to the #pragma config directive, as in
    #pragma config WDTE=ON, FOSC=XT, CPD=ON
    No migration is required if the #pragma config was already used

    Ответить

  5. Аааа. Я ничего не понимаю на английском :) Поясните пожалуйста. А почему тогда на #fuses не ругается?
    А остальное все так же как и в хайтеки? include и т.д. у остального. Только вместо __CONFIG #pragma confiп?

    Ответить

    sarge Ответил:

    Да, #pragma config

    Не совсем все, к портам доступ по другому организован и названия регистров могут отличаться, но это все решается в считанные секунды.

    Почему не ругается на фьюзы – понятия не имею, но упоминания о такой директиве нету в мануале на xc8.

    Ответить

    Василий Ответил:

    Подскажите пожалуйста как мне такое написать?

    __CONFIG(WDTDIS & UNPROTECT & MCLRDIS & INTOSCIO);
    чтобы таймер отключить, чтоб работало от внутреннего генератора и чтоб был сброс при малом питании… Не знаю что такое LVP у Вас.
    #pragma config MCLRE = OFF — так у меня нормально, но вот когда хочу другие опции записать… Все ругается….

    Ответить

    Василий Ответил:

    Все, разобрался, не важно, спасибо)

    Ответить

    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="">