вторник, 13 января 2015 г.

Работа в MPLABX

<< Назад к оглавлению

Для начала создадим новый проект
File->new project->Standalone project
Затем выбирается контроллер
Отлаживать будем через симулятор
Далее выбирается пакет. Если вы хотите писать на Си, то соответственно должен быть установлен компилятор
И далее вводим имя проекта. и кодировку UTF-8

Слева появится окно проекта со всеми файлами.
Файл линковщика нам не нужен. файлы .C и .asm должны лежать в source files, .h в header Files.

Чтобы создать новый файл, щелкаем правой кнопкой мышки, new и соответствующий файл. Для .asm нужно создать empty file и добавить расширение .asm
Скомпилировать проект Run->Clean and build Main project
По идее MPLABX может сам прошивать контроллеры, но он не полностью поддерживает программатор pickit2, Поэтому приходится пользовать HEX файл. Он будет лежать в: Каталог вашего проекта/dist/default(или название настройки)/production
File->project properties вызовет следующее окно
Где в XC8 global options можно задать смещение кода, чтобы прошивать программу бутлоадером. А во вкладке General - папки, в которых будет производиться поиск файлов.

Конфигурационные биты

Необходимо их настроить. Для этого идем в Window->PIC memory views->configuration bits

откроется окно, и выставляем там FOSC=INTOSCIO, WDT=OFF, MCLRE=OFF
Щелкаем правой клавишей и Generate Source Code to Output. Эта опция создаст код, необходимый для задачи конфигурационных битов. 
Копируем код, создаем файл заголовков config.h и вставляем сгенерированный код в конец файла.

Отладка программы.

установим точку остановки. Тыкаем на номер строки
И жмем debug->debug main project
программа остановлена в заданной точке
И мы можем пошагово эмулировать работу программы. F8 - следующий шаг, не заходя в функции, F7 - заходя.
В окне Watches можно ввести интересующие переменные и отслеживать как они изменяются по ходу работы. Вызывается window->debugging->watches
Через Stimulus и IO pins можно эмулировать напряжения на ножках контроллера и изменения регистров. включаются окна в window->simulator

Если вы зайдете в window->pic memory views,
то можно посмотреть изменения в процессе работы программы на регистры спец. назначения (SFR registers)
Либо память для хранения переменных (File registers)
Конфигурационные биты (Configuration bits)
и память программы. Вместе со строками дизассемблера (Program memory)





понедельник, 12 января 2015 г.

CAN интерфейс и контроллер pic18f2550 (XC8). Модуль MCP2515

<< Назад к оглавлению

Старую версию для компилятора C18 можно найти здесь
Мы будем говорить о контроллере pic18f2550, поскольку только он сейчас есть у меня перед глазами. Но все нижесказанное должно быть справедливо и для pic18f4550.
В этом контроллере есть специальные встроенные возможности общаться с периферией, но нету возможности создать сеть штатными средствами.
Предположим, что необходимо создать связь между несколькими отдаленными контроллерами. Можно конечно продумать то, как они будут общаться, написать для этого программу и установить усилители сигналов, чтобы их можно было передать на дальние расстояния. Но не много ли работы?
Есть множество готовых решений, с помощью которых можно это сделать.
Мы будем рассматривать CAN интерфейс. Он изначально был предложен фирмой Bosch и в сети есть множество информации, описывающей can интерфейс.
В двух словах о нем.
- передача идет по двум проводам
- настраивается скорость передачи информации
- существует механизм проверки сообщений
- гарантированная доставка сообщений.
На самом деле мне кажется абсолютно неважным описывать что-то столько раз документированное.
http://ru.wikipedia.org/wiki/Controller_Area_Network
Так же официальная спецификация на стандарт CAN 2.0
http://www.bosch-semiconductors.de/media/pdf_1/canliteratur/can2spec.pdf

Есть специальный интерфейсный контроллер CAN от фирмы microchip MCP2515
http://ww1.microchip.com/downloads/en/DeviceDoc/21801G.pdf
Это специальное "добавление" к контроллеру, осуществляющее реализацию сети CAN. И для этого контроллера еще нужен будет передатчик MCP2551
http://ww1.microchip.com/downloads/en/DeviceDoc/21667f.pdf
Ниже показано подключение pic18f2550 к MCP2515
Файлы проекта:
здесь
Проект рассчитан на то, чтобы быть прошитым через bootloader. Если вы прошиваете через программатор, то необходимо сделать следующее: удалите строку в File->project properties->XC8 global options->additional options. Она задает смещение кода для бутлоадера

Общение между pic18f2550 и MCP 2515 происходит с помощью протокола SPI, созданного для общения с периферийными устройствами.
Для SPI используются соответствующие ноги SDI SDO SCK и CS
причем SDI (input) mcp2515 нужно подключить к SDO (output) pic18f2550. А в качестве CS используется любой цифровой вывод контроллера.

В проекте следующие файлы
main.c - основной файл команды
io.h - файл, в котором настроены вводы выводы pic18f2550
mcp2515.h - адреса регистров и команд внутри модуля MCP2515
spi_functions.h - файл для работы со SPI интерфейсом
config.h - конфигурационные биты

Все необходимые комментарии даны непосредственно в коде программы

В программе используются следующие специфические комманды

Настройка контроллера производится в функции userinit(); и в последствии в CANinit();
нужно выставить соответствующие пины контроллера на вывод (SDO,SCK) и ввод (SDI) - читай подробнее в комментариях к контроллеру.

потом идет перезагрузка контроллера и модуль CAN переводится в конфигурационный режим. Все основные настройки можно делать только в этом режиме. Настраиваются соответствующие конфигурационные регистры. Во-первых bit-timing (CNF1,CNF2,CNF3). Все узлы сети CAN должны работать на одной тактовой частоте.

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

У контроллера MCP2515 есть возможность отправлять сообщение при высоком сигнале на входах RTS. Мы отключаем их. Будем отправлять с помощью команд, передаваемых через SPI.
настраиваем прерывания. Например, когда контроллер увидит сеть CAN вывод INT будет нулем. По умолчанию на нем будет 1.
Так же настраиваются RX0BF и RX1BF. Когда буфер 0 будет заполнен, на RX0BFпропадет напряжение.
Потом мы включаем нормальный режим, в котором контроллер работает.

А потом передаем сообщение (по факту передастся при первой возможности - подключении к CAN сети). И просто мигаем светодиодом на RA2 когда сообщение передано

Проверить работу вы сможете, когда у вас 2 таким образом сконфигурированных контроллера, или другой узел CAN. Светодиод будет мерцать после передачи сообщения. Если он просто горит - то не проходит конфигурация модуля MCP2515


У модуля CAN есть множество возможностей. Советую почитать спецификацию CAN и техническое описание MCP2515.

Подключение узлов осуществляется следующим образом.

То, что указано на схеме подключения имеет выводы CANH и CANL это и должно быть подключено к сетевым линиям.

Прошу спрашивать, если что-либо непонятно или требует дополнительного рассмотрения.

Файл настроен на работу 125Кб/с
Рассчитывается скорость работы CAN (NBR) модуля следующим образом:
TQ=2*(BRP+1)/Fosc
Fosc - частота генератора на MCP2515
BRP - Делитель частоты. Задается в коде
Tbit=Tsync+Tprop+TPS1+TPS2
Tsync=TQ
Остальные же величины задаются а коде программы
NBR=1/Tbit

пятница, 9 января 2015 г.

Урок 5. USB. Сторона контроллера (обновлено 25.04.2015)

<< Назад к оглавлению

Найдена ошибка. В старом проекте для грамотной работы под бутлоадер нужно было указать --CODEOFFSET=1000 в настройках проекта. XC8 global options->additional opptions. Спасибо Глебу Галиеву. 

Это переработанная статья. В ней используется пакет MPLABX и компилятор XC8. Старую статью можно найти здесь. 
Все, теперь добрались мы до чего-то интересного. Протокол USB.
Наша схема будет аналогична приведенной в уроке 3 про бутлоадер.
Я проверял на PIC18f2550 но и на PIC18f4550 должно бы работать.


Только еще пару ножек контроллера мы будем использовать, как датчики, чтобы проверить, правда ли все у нас работает.
Файл проекта: Ссылка
Здесь вы найдете сам проект для MPLABX и программы для компьютера, через которые идет общение с USB устройством.

ВАЖНО! Проект собран для работы с бутлоадером. Если вы прошиваете через программатор, то необходимо сделать следующее: удалите строку в File->project properties->XC8 global options->additional options. Она задает смещение кода для бутлоадера.

Этот пример - копия с hid - custom demo из пакета MLA. Поскольку в оригинале он обращался к библиотекам через относительный путь как ../../../../Microchip/usb и.т.д. То для быстрой работы надо установить MLA и положить проект так же как примеры. В тот же каталог. Внизу статьи написано как запустить оригинальный файл. В моем варианте удалены все файлы, которые не относятся к нашему контроллеру, добавлены комментарии. Переделан немного код, для того, чтобы он запускался для обоих контроллеров: 2550 и 4550. и USB библиотека и некоторые настройки контроллера перенесены в папку проекта.
Контроллер наш, поскольку имеет аппаратную поддержку протокола USB имеет в своей памяти определенные места, в которые нужно записать настройки usb. это первый главный момент. В основном все это находится в файле usb_descriptors.c. Вы можете открыть этот файл и посмотреть комментарии или даже отредактировать.
И в теле программы мы будем вызывать функцию USBDeviceTasks(), которая выполняет в общем-то всю работу по обмену информации через USB.
Плюс, нужно определить некоторые стандартные функции, которые вызываются при получении нашим устройством различных команд, в момент подключения к хосту например. без них, устройство так и не сможет обнаружиться. Эти команды находятся в функции USER_USB_CALLBACK_EVENT_HANDLER файла main.c и особенно здесь не рассматриваются, так как они осуществляют рутинную стандартную работу и вы будете вряд ли их менять.
На данный момент библиотека работает следующим образом:

Функция USBDeviceTasks()

Для того, чтобы поддерживать работу USB, когда хост обращается к устройству с сообщением, в течение определенного времени устройство должно дать ответ. В случае, если это не происходит, хост может просто отключить наше устройство, посчитав его сломанным.
Чтобы обработать usb сообщение и выслать ответ, нужно вызвать функцию этой библиотеки:
USBDeviceTasks(); ну и чтобы отправилось правильное сообщение надо подготовить буферы вывода и прочее.
В нашем примере мы будем вызывать эту функцию через прерывания от USB модуля. Есть и другой выбор: для того, чтобы вовремя давать ответ хосту, можно просто использовать цикл.

USB дескрипторы

Для корректной работы нашего устройства нужно будет задать USB дескрипторы. В общем-то это описание нашего устройства. Они содерждат класс устройства, в нашем случае это - HID (Human Interface Device, которым могут быть мышки, клавиатуры, или вообще любое устройство) и имя устройства. Все эти параметры заданы в файле usb_descriptors.c, который уже добавлен в проект. Перед началом работы хост с устройством обмениваются дескрипторами, это дает понять, каким образом будет осуществляться взаимодействие устройств.

Файлы adc.c leds.c button.c

В этих файлах находятся простенькие функции, как например, мигнуть светодиодом, считать АЦП, проверить, нажата ли кнопка.

Файл app_device_custom_hid

В этом файле находится функция UserHIDTasks(), которая собственно и делает всю работу. Мы ее вызываем из основного цикла файла main.c. Вся обработка команд от хоста происходит в этой функции. И все действия - тоже через нее.

Комментарии к программе

Напоминаю, что USB устройство может передать данные только по запросу с хоста.
В проекте, который залит сюда, указан сдвиг для работы с bootloader'ом. Для того чтобы его убрать - удалите строку в File->project properties->XC8 global options->additional options. Она задает смещение кода для бутлоадера.

Суть такая: у нас есть наш функции и функции usb библиотеки. Сначала в main.c происходит инициализация, потом просто крутится главный цикл программы. Через него все и работает. Через прерывания вызывается USBDeviceTasks(). Контроллер через модуль USB получает информацию от хоста (компьютера), и тот "просит" контроллер сделать то или иное действие. переключить светодиод, или отправить какую-то информацию. Если мы отправляем информацию, то она кладется в буфер, и уходит со следующим USBDeviceTasks().

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

Оригинальный проект из MLA

Вот как собрать оригинальный проект. Но я надеюсь, что вам хватит и моего проекта, вверху этой страницы
Нам понадобится пакет Microchip Libraries for Applications (MLA) Ссылка зеркало
Качаем этот файл и устанавливаем.
Мы будем собирать пример HID - custom demo
лежит он в папке с установленной программой:
\microchip\mla\v2014_07_22\apps\USB\Device\HID - Custom\firmware
Внутри в папке firmware - прошивка для контроллера. В остальных - программы для компьютера.
Дело в том, что в Microchip libraries каждый проект создан для десятка разных контроллеров, и учиться на этом коде довольно проблематично. В проекте есть несколько настроек для разных контроллеров. выбираются эти настройки через File->Project properties->Manage configurations
 Изначально из наших контроллеров там присутствует только pic18f4550 и для этого нужно открыть настройку проекта PICDEM FSUSB.mcp
Это по идее для такой учебной платы picdem fsusb. Она как раз работает на контроллере pic18f4550.
Распиновка там другая. Вы увидите в таких файлах как led.c button.c. Я специально поменял используемые ножки контроллера, чтобы программа запускалась не только на pic18f4550 но и на 18f2550.
Если у вас именно 18f2550, то в настройках проекта можно поменять контроллер с pic18f4550 на 2550.
Все файлы настроек лежат в папках проекта, например, system_config\picdem_fusb

воскресенье, 28 декабря 2014 г.

Простой код на С. Компилятор XC8

<< Назад к оглавлению

Я плавно переделываю уроки на использование пакета MPLABX и компилятора XC8. Так как старые уже не поддерживается. Тем не менее, вы можете найти старую статью здесь. Так же точно можете скачать компилятор C18 и использовать его. XC8 несколько отличается

Итак, нам понадобится компилятор XC8. Его можно скачать с официального сайта. ссылка, либо же с зеркала зеркало

Итак, создаем проект в MPLABX
Это делается примерно так же как во втором уроке, только выбираем компилятор XC8

 Это аналог программе, написанной в уроке 2.
#include <p18f2550.h>
#include <stdio.h>
#include <stdlib.h>
#include <p18f2550.h>
#include "config.h"


void delay(void)
{
long i;
for (i=0;i<100000;i++);
}

int main(int argc, char** argv) {
  TRISA = 0;
  PORTA = 0;
  while (1)
  {
  PORTAbits.RA2 = 1;
  delay();
  PORTAbits.RA2 = 0;
  delay();
};
    return (EXIT_SUCCESS);
}
Сначала запускается функция main(). Идет настройка вывода сигнала через порт А (TRISA=0;) а потом обнуляется этот выход с порта А (PORTA=0); Далее идет бесконечный цикл, в котором мы мигаем лампочкой на порту RA2 и вызываем функцию задержки.
Пока что у вас не скомпилируется этот проект. Потому что в include стоит файл config.h, а мы пока его еще не создали. Там будут конфигурационные биты.
Необходимо их настроить. Для этого идем в Window->PIC memory views->configuration bits

откроется окно, и выставляем там FOSC=INTOSCIO, WDT=OFF, MCLRE=OFF
Щелкаем правой клавишей и Generate Source Code to Output. Эта опция создаст код, необходимый для задачи конфигурационных битов. 
Копируем код, создаем файл заголовков config.h и вставляем сгенерированный код в конец файла.

Все обозначений навроде портов и встроенных устройств можно найти в файле p18f2550.h или p18f4550.h, так же всегда вы можете обратиться к ТО на контроллер.
директива #include <p18f2550.h> подключает заголовки для контроллера
#pragma config - Это опять же выбор конфигурационных битов для контроллера. См урок №2.
Эти настройки у нас хранятся теперь в файле config.h 

Если вы будете использовать этот код с бутлоадером. А это намного удобнее, нам необходимо сдвинуть его в памяти программы на 0x1000. Если в C18 компиляторе для этого была специальная директива, то теперь для этого служит настройка компилятора. Грубо говоря, теперь когда мы пишем код в XС8, компилятор сам знает где должны быть прерывания, как размечена память, и.т.д. Все, что мы можем сделать - это сделать сдвиг. 
Итак, чтобы программа корректно работала с бутлоадером, нужно сделать следующее:
File->Project properties
Потом XC8 global options (не XC8 compiler options, специально на это обращаю внимание), и пишем в поле additional options

--CODEOFFSET=1000

Это означает, что весь код компилируется со сдвигом в 0x1000



Если вы захотите вставить код ассемблера в файл Си, то вам нужно будет его заключить между директивами

#asm

#endasm

Файлы проекта: ссылка

вторник, 23 декабря 2014 г.

Второй урок. Простой код на ассемблере и устройство вкратце.


<< Назад к оглавлению

В данном тексте приведены ссылки на книги. "название книги":страница обозначает указатель на определенную страницу книги. "название книги":Гглава - главу. При этом ТО - сокращение для тех. описания контроллера (Datasheet). Например ТО:15 - 15 страница технического описания. ТО:Г3 - третья глава технического описания
 
Эта статья переработана. Существует так же старая версия с оболочкой MPLAB 8.91. Прочесть ее можно здесь.

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

Итак, что такое контроллер, и как он работает?
Конечно же, это просто черный жучек с ножками. За неимением никаких других членов, он общается с окружающим миром исключительно напряжением на ножках. Что в общем и демонстрировалось в программе в первом уроке. Просто с определенной переодичностью контроллер зажигал
светодиодик.
В расcматриваемых нами контроллерах память разделена. Программа записывается в отдельное пространство, именуемое памятью программы (PROGRAM MEMORY). Переменные и настройки хранятся в памяти данных (DATA MEMORY). Причем, ячейки памяти, выделенные для использования как переменные называются регистрами общего назначения (GENERAL PURPOSE REGISTERS или GPR) и настройки находятся в регистрах специального назначения (SPECIAL FUNCTIONS REGISTERS или SFR). Память данных поделена на 15 блоков и блоки меняются регистром BSR (BLOCK SELECT REGISTER).
Так же существует EEPROM memory - это флеш память, используемая для длительного хранения информации.
Подробнее о памяти контроллера смотри главу 1 ссылка.

Код программы


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

Ладно, начнем.

Открываем MPLABX IDE жмем File->New Project. В открывшемся окне выбираем Microchip Embedded Standalone Project


 выбираем семейство контроллеров advanced 8 bit MRUs и наш контроллер, например pic18f2550
Next, Next.Теперь компилятор предлагает нам выбрать соответствующий набор для разработки. К этому моменту должно быть установлено все необходимое.
Первый урок на ассемблере, поэтому выбираем MPASM. Далее. Задаем имя и прочие свойства. Укажите кодировку с русским. Например. UTF-8. Иначе ваши комментарии на кириллице не сохранятся.

И вот проект открыт. По началу в нем есть только makefile. Это файл для сборки проекта. Поэтому щелкаем на Source files->new->empty file

Ну назовем его например main.asm
Переписываем туда программу. Вот код:

Листинг source.asm


  #include <p18f2550.inc> ;подключение заголовков
list p=18f2550 ; выбор контроллера
CONFIG FOSC=INTOSCIO_EC ; Выбран внутренний генератор
  CONFIG MCLRE = OFF ; отключаем сигнал сброса
  CONFIG WDT   = OFF ; отключаем сторожевой таймер

DELAYCOUNTER EQU 0x00  ; задаем две переменные для создания задержки (паузы)
DELAYCOUNTER1 EQU 0x01; в программе. Они по адресу 0x00 и 0x01
A EQU 0; под буквой A будем подразумевать, что используется access bank

ORG 0 ; начинаем с 0 адреса памяти программы
  GOTO main ; перейти на метку main
  ORG 28h ; теперь пишем с 28 адреса. (сделано это для работы с прерываниями)
main ;(начинается программа main- просто метка для нашего удобства)


  CLRF BSR,A;       ; - выбираем нулевой блок памяти данных
  CLRF PORTA,A       ; - обнуляем выход на порту а    ;

  CLRF WDTCON,A; выключаем сторожевой таймер
  MOVLW 0x0F       ; записываем 0x0F в аккумулятор
  MOVWF ADCON1,A    ; перебрасываем значение в ADCON1 - настраиваем порт A на цифровой вход/выход
  CLRF TRISA,A ;- настраиваем порт а - только на выход
  
endloop ; это цикл, в который будет без конца гонять наша программа
  BTG LATA,2,A; мигнуть светодиодом 
  CALL delay255; вызвать паузу
  GOTO endloop; вернуться к началу цикла

delay255 ; функция вызова паузы
  SETF DELAYCOUNTER,A; записать 0xFF в счетчик времени
  GOTO delay; перейти к delay
delay 
  SETF DELAYCOUNTER1,A; записать 0xFF во 2й счетчик времени
delaysub1 ;
  DECFSZ DELAYCOUNTER1,F,A; уменьшить 2й счетчик на 1. если >0
  GOTO delaysub1; то вернуться на шаг назад
  DECFSZ DELAYCOUNTER,F,A; иначе - уменьшить 1й счетчик, если >0
  GOTO delay; вернуться на метку delay
  RETLW 0; иначе - выйти из функции

END ;конец программы

Для контроллера pic18f2550
https://yadi.sk/d/1YkpyyJTVLg2V
Для контроллера pic18f4550
https://yadi.sk/d/FxMGleO_VLgp7 - к сожалению не могу сейчас проверить
для копиляции щелкаем Run->build main project

после компиляции у нас должен в папке проекта появиться HEX файл. Он находится в папке dist\default\production. Его можно и нужно прошить в контроллер. Это та же программа, что и в уроке 1.
На самом деле среда MPLABX умеет работать с программаторами, но у меня PICkit 2 и с ней она работает посредственно, поэтому я прошиваю HEX файл напрямую через PICKIT

Пояснения к коду программы



Начнем потихоньку разбирать что там написано

В самом верху указываем то, какой у нас будет контроллер
#include <pic18f2550.inc>
Мы их рлдключаем для того. чтобы вместо того, чтобы всегда и везде мы записывали цифрами. мы могли использовать некоторые уже привычные нам обозначения.
напирмер, без подключения заголовков. команда записи в регистр выбора блока (BSR) -строка 16 нашей программы выглядела бы так
MOVWF 0FE0;

так... Еще директива. 
list p=18f2550
Она просто говорит
компилятору, какой контроллер будем прошивать. 

Дальше уже интереснее. Нам нужно задать управляющее слово. это - настройки контроллера. 
Задает их директива CONFIG 
По поводу всех настроек контроллера обращаемся так же к техническому описанию. ТО:288


Конфигурационные биты


CONFIG FOSC=INTOSCIO_EC
Эта настройка говорит о том, что мы будем использовать внутренний генератор импульсов. Он - внутри контроллера. Читаем в ТО:25

CONFIG MCLRE = OFF
Здесь мы отключаем сигнал сброса. То есть контроллер будет включаться сразу с подачей на него питания.

CONFIG WDT = OFF
Отключаем сторожевой таймер. Просто. чтобы не "запариваться". Он служит защитой от зависания контроллера. Читаем в ТО:299

Более подробно конфигурационные биты рассмотрены во 2-й главе к этому уроку. ссылка

Тело программы


DELAYCOUNTER EQU 0x00
Эта директива (EQU) ставит в соответствие к DELAYCOUNTER 0x00
То есть мы пишем DELAYCOUNTER, а программа думает "0x00"
Вообще мы будем использовать DELAYCOUNTER как переменную. а 0x00 - просто адрес, где она хранится в общих регистрах.
Кстати. Забыл сказать. 0x00 - это просто число. Так мы записываем числа в 16ричной системе счисления.
то есть 0x6B = 107

Мы используем для нашей программы память, входящую в access RAM, поэтому мы вольны использовать ячейки памяти от 0x00 до 0x5F. А ячейки от 0x60 до 0xFF - это регистры общего назначения.

ORG 0
Этим мы указываем компилятору, чтобы он писал все последующие команды последовательно с адреса 0.
GOTO main
ORG 28h
main
Переходим на метку main. И начиная с 0x28 адреса пишем программу дальше. Метка main - адрес 0x28
Обратите внимание, мы оставили свободное место между адресом программы 0x1 и 0x28. Зачем? Если мы будем в последствии использовать прерывания, то в случае. если прерывание будет требовать на время приостановить программу. оно начнет выполнять команды по адресу 0x8 или 0x18. и это место нужно будет заполнить программой обработки прерывания.

Все последующие команды смотри в главе 3. Команды ассемблера. ссылка

MOVWF ADCON1
Когда мы записываем значение в регистр ADCON1. мы меняем настройки АЦП. По поводу 
использования встроенных устройств контроллера смотри главу 4. ссылка


Пожалуйста, помогите сделать статью лучше. Увидели непонятность, неточность или  ошибку, сообщите в комментарии, или напишите мне. Спасибо. Jasuramme@mail.ru

воскресенье, 29 июня 2014 г.

CAN интерфейс и контроллер pic18f2550

<< Назад к оглавлению

ЭТО УСТАРЕВШАЯ ВЕРСИЯ. НОВУЮ МОЖНО НАЙТИ Здесь
Мы будем говорить о контроллере pic18f2550, поскольку только он сейчас есть у меня перед глазами. Но все нижесказанное должно быть справедливо и для pic18f4550.
В этом контроллере есть специальные встроенные возможности общаться с периферией, но нету возможности создать сеть штатными средствами.
Предположим, что необходимо создать связь между несколькими отдаленными контроллерами. Можно конечно продумать то, как они будут общаться, написать для этого программу и установить усилители сигналов, чтобы их можно было передать на дальние расстояния. Но не много ли работы?
Есть множество готовых решений, с помощью которых можно это сделать.
Мы будем рассматривать CAN интерфейс. Он изначально был предложен фирмой Bosch и в сети есть множество информации, описывающей can интерфейс.
В двух словах о нем.
- передача идет по двум проводам
- настраивается скорость передачи информации
- существует механизм проверки сообщений
- гарантированная доставка сообщений.
На самом деле мне кажется абсолютно неважным описывать что-то столько раз документированное.
http://ru.wikipedia.org/wiki/Controller_Area_Network
Так же официальная спецификация на стандарт CAN 2.0
http://www.bosch-semiconductors.de/media/pdf_1/canliteratur/can2spec.pdf

Есть специальный интерфейсный контроллер CAN от фирмы microchip MCP2515
http://ww1.microchip.com/downloads/en/DeviceDoc/21801G.pdf
Это специальное "добавление" к контроллеру, осуществляющее реализацию сети CAN. И для этого контроллера еще нужен будет передатчик MCP2551
http://ww1.microchip.com/downloads/en/DeviceDoc/21667f.pdf
Ниже показано подключение pic18f2550 к MCP2515
Файлы проекта:
https://yadi.sk/d/7MknbTTtVNWJD
Проект рассчитан на то, чтобы быть прошитым через bootloader.

Общение между pic18f2550 и MCP 2515 происходит с помощью протокола SPI, созданного для общения с периферийными устройствами.
Для SPI используются соответствующие ноги SDI SDO SCK и CS
причем SDI (input) mcp2515 нужно подключить к SDO (output) pic18f2550. А в качестве CS используется любой цифровой вывод контроллера.

В проекте следующие файлы
2550can.c - основной файл команды
io.h - файл, в котором настроены вводы выводы pic18f2550
mcp2515address.h - адреса регистров внутри модуля MCP2515
spi.h - файл для работы со SPI интерфейсом

В программе используются следующие специфические комманды

OpenSPI(SPI_FOSC_16, MODE_00, SMPMID)  - Настройка регистров, связанных со SPI модулем

WriteSPI(msg)  - записать через SPI интерфейс сообщение msg

ReadSPI(msg)  - Возвращает прочитанный байт через SPI
в коде программы определены следующие функции, выполняющие действия с контроллером MCP2515

SPIByteRead(адрес) - прочитать регистр по адресу
SPIReset() - перезагрузить
SPImsg() - передать через SPI одно сообщение
SPIByteWrite(адрес,сообщение) - записать в адрес сообщение
transmitmsg() - передать сообщение

Настройка контроллера производится в функции userinit(); и в последствии в CANinit();
нужно выставить соответствующие пины контроллера на вывод (SDO,SCK) и ввод (SDI) - читай подробнее в комментариях к контроллеру.

потом идет перезагрузка контроллера и модуль CAN переводится в конфигурационный режим. Все основные настройки можно делать только в этом режиме. Настраиваются соответствующие конфигурационные регистры. Во-первых bit-timing (CNF1,CNF2,CNF3). Все узлы сети CAN должны работать на одной тактовой частоте.

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

У контроллера MCP2515 есть возможность отправлять сообщение при высоком сигнале на входах RTS. Мы отключаем их. Будем отправлять с помощью команд, передаваемых через SPI.
настраиваем прерывания. Например, когда контроллер увидит сеть CAN вывод INT будет нулем. По умолчанию на нем будет 1.
Так же настраиваются RX0BF и RX1BF. Когда буфер 0 будет заполнен, на RX0BFпропадет напряжение.
Потом мы включаем нормальный режим, в котором контроллер работает.

А потом передаем сообщение (по факту передастся при первой возможности - подключении к CAN сети). И просто мигаем светодиодом на RA2

Проверить работу вы сможете, когда у вас 2 таким образом сконфигурированных контроллера, или другой узел CAN. И проверять пропадание напряжения на RX0BF и INT.
Если ни один из этих пинов не имеет напряжения даже без сети, значит проблема с реализацией SPI интерфейса.

У модуля CAN есть множество возможностей. Советую почитать спецификацию CAN и техническое описание MCP2515.

Подключение узлов осуществляется следующим образом.

То, что указано на схеме подключения имеет выводы CANH и CANL это и должно быть подключено к сетевым линиям.

Прошу спрашивать, если что-либо непонятно или требует дополнительного рассмотрения.




пятница, 27 сентября 2013 г.

Урок 6. USB. Сторона компьютера

<< Назад к оглавлению

В прошлом уроке мы собирали прошивку для контроллера, чтобы он работал через USB. Но для взаимодействия с компьютером нам нужна еще и специальная программа, которая будет запускаться на компьютере.
Вот сейчас мы и будем ее создавать.
Опять же в пакете Microchip solutions есть пример, для нашего контроллера, но я переписал его по своему. Во-первых я сделал без использования графического интерфейса, и размер кода уменьшился раза в 3-4. Что намного лучше для изучения. Тем не менее, принцип работы один. код в стандартном примере от microchip работает так же как этот.
Программа написана в C++. Проект собран в бесплатной студенческой версии Visual C++ express 2010. Я буду давать общие идеи и комментарии по коду, но подразумеваю, что вы уже имеете хоть какой-то опыт программирования в C++.
Итак, начинаем

Здесь находится весь проект, включая исходный текст ссылка

Для того, чтобы читать и записывать данные через USB порт нам нужно получить указатель на наше устройство. Поскольку в отличие от старых портов, подключено может быть устройств свыше сотни, то получить этот указатель не так-то просто. Для того, чтобы это сделать мы будем обращаться к драйверам windows, а именно SetupAPI. Кстати, как только мы получим указатель, то будем общаться с USB портом, будто бы это файл.
Передача данных будет занимать лишь пару команд. Но вот подготовка!
Поскольку мы программируем в С++ то нам нужно быть очень аккуратными с типами данных.
Создаем консольный проект win32. И добавляем туда единственный файл main.cpp

Итак, нам необходимо подключить некоторые библиотеки.
#include <iostream>
#include <Windows.h>
#include <setupapi.h>

Так же подключаем внешнюю библиотеку:
#pragma comment (lib, "Setupapi.lib")

Первая описанная функция в программе - это getUSBHandle(). Ее описание - в комментариях кода. Да и вообще основные комментарии приведены в коде. Она служит для того, чтобы найти наше устройство и подготовить указатели, чтобы мы могли записывать в устройство и читать из него.
Если в двух словах, то она использует стандартные windows функции для доступа к драйверам USB и через них получает указатель на само устройство.
Если интересно, что все эти функции делают и как, то обращайтесь к MSDN или к книге Агурова, что лежит в оглавлении. Что важно знать: у каждого устройства есть путь, и нам важно получить его. Мы сначала проверяем, совпадает ли ID с устройством, что мы ищем. А потом находим путь устройства.Мы ищем только среди устройств HID класса. это определяется в переменной Guid. Остальное см в комментариях программы
Следующая функция - writeReadUSB. Это просто вспомогательная функция, которая записывает в наше устройство. Обращаю внимание, что запись и чтение устройства после того, как мы создали указатель на него реализуется с помощью стандартных комманд WriteFile и ReadFile
И после этого уже мы видим функцию main с которой и начинается выполнение программы. Она вызывает getUSBHandle, пока мы не получим указатель на устройство, потом читает с клавиатуры комманду и в зависимости от нее, передает и читает данные с USB устройства.
В проекте по ссылке выше лежит исходный код с комментариями и сама скомпилированная программа. Удачи.

В процессе поиска ошибки я наткнулся на библиотеку hidapi. Она является кроссплатформенной. И Только для работы с hid устройствами. Очень проста в использовании. Привожу проект под нее. ссылка.
Hidapi скачан с официального сайта. Для того чтобы начать проект нужно добавить setupapi.lib в линковщик. project->properties->linker->input и подписать туда setupapi.lib;
Удачи.
Нашел пристойное описание библиотеки здесь: http://microsin.net/programming/PC/multi-platform-hid-api.html.
Спасибо!