Не так давно я написал статью о мое ремесло на базе микроконтроллера Silicon Labs C8051F320. Пришло время поговорить о программировании этого микроконтроллера для простых задач.
Подробности под катом.
Итак, в предыдущей статье я рассказал о небольшой платке, которая должна стать основой будущего устройства.
На нем расположен сам микроконтроллер и его небольшая приставка, предназначенная для сброса прошивки, питания микроконтроллера и т.п.
Одной из задач, которые приходилось выполнять этому устройству на нашей работе, было управление некоторыми устройствами на исследовательском стенде.
Так как, по сути, задача была не очень сложной, то и прошивка для МК не требовала каких-то сложных решений вроде работы с USB и других специфических вещей, но анализ этой прошивки может в будущем оказать большую помощь тем, кому придется работать с подобным МК для учебы (Мой друг вроде как сейчас в рамках учебы программирует 51-е ядро) или для работы.
Но обо всем по порядку.
Задача
Задача была поставлена достаточно простая — организовать простейшее включение/выключение удаленных устройств с микроконтроллера, организовав необходимые задержки между операциями.По идее нужно было еще управлять этими задержками с ПК через USB, но как оказалось позже, это не так важно.
Аппаратное обеспечение
Для решения этой проблемы пришлось реализовать аппаратную часть устройства, отвечающую за сопряжение микроконтроллера с удаленными устройствами, поскольку само «сердце» не несло на борту ничего подобного и изначально проектировалось для управляется периферийной платой.На железе особо останавливаться не буду, так как статья про прошивку, но все же для полноты картины приведу ее схему и краткое описание.
Всего было 6 удаленных устройств, три из которых управлялись по оптоволокну, два через реле и одно простым импульсом в 5 вольт. Так как наше начальство не любит, чтобы все было сделано по уму и соответственно не хочет выделять деньги на грамотную работу, то принципиальная схема составлялась быстро и на коленке, поэтому в ней могут быть мелкие недочеты.
Вот она.
Убедившись, что никаких изменений в устройстве не предвидится, а точнее, уточнив у начальства, что никакого «Ой, посмотрим…», после которого нам придется делать совершенно новую схему, мы приступили к изготовлению.
печатная плата.
Про отсутствие денег я уже говорил, поэтому скажу лишь, что все делалось из подручных элементов - плата вытравлена на коленке из куска старой печатной платы, элементы нашлись в кладовке.
В общем, полная разруха.
НИИ, что еще сказать.
В общем, результат виден на фото:
Кстати, потом все получилось «Ой, посмотрим.
», поэтому пришлось склепать пару маленьких платков, прорезать дорожки на этом и соединить все это соплями, но пост не об этом.
Программная часть
Описание программной части будет состоять из нескольких подпунктов, чтобы было легче читать и понимать, о чем идет речь.Алгоритм работы Алгоритм прост как сапоги:
- Проверяем наличие внешнего сигнала «Пуск» от вышестоящего устройства
- Если сигнал получен, отрабатываем заданную последовательность, не заботясь о проверке работы устройств.
Кстати, этот метод мне показался не совсем корректным, поэтому одну проверку я все же сделал, чтобы не случилось, но просто реализовал его аппаратно, а не в прошивке.
- Вернемся к пункту первому
Конфигурация микроконтроллера Что мне нравится в SILabs, так это то, что у них есть куча вкусностей в виде программ для инициализации, настройки, прошивки и непосредственной отладки их микроконтроллеров.
Итак, берем их программу для первоначальной настройки МК с их сайт и запустите его.
Выбираем в настройках нужный нам микроконтроллер и начинаем настройку.
В процессе настройки МК нам нужно будет настроить его порты ввода/вывода так, чтобы в исходном состоянии они имели логический ноль, установить таймер-счетчик на нужный нам интервал (ЕМНИП я установил на 50 микросекунд), включить прерывания по таймеру и прочие мелочи.
Все точно не помню, делал давно, просто покажу пример.
В меню «Свойства» выбираем нужный нам пункт и видим открывшееся окно, где в GUI настраиваются все нужные нам параметры.
При нажатии кнопки ОК все настройки копируются в окно кода.
МК мы настроили, но закрывать конфигуратор не спешим, он там еще понадобится.
Скачать с тот же сайт Силиконовая лаборатория IDE , с помощью которого мы будем прошивать МК.
Давайте запустим его.
Здесь есть один нюанс: ей нужно дать компилятор от Keil C51, чтобы она могла им пользоваться.
Не буду на этом останавливаться, просто покажу на картинке, как это делается.
Откройте меню Проект — Интеграция цепочки инструментов и укажите пути к ключевым компиляторам.
Откройте конфигуратор и скопируйте из него полученный код в IDE.
Реализация основной задачи Итак, МК настроен, приступаем к реализации основной задачи – проверяем входящий сигнал и отрабатываем последовательность.//--------------------------------------------------------------------------------// // Initialization of timer // //--------------------------------------------------------------------------------// void timerInit(void) { TMOD = 0x10; TMR2CN = 0x24; TF2LEN = 1; TMR2RLL = 0xCF; TMR2RLH = 0xFF; TMR2L = 0xCF; TMR2H = 0xFF; T2SPLIT = 0; T2SOF = 0; ET2 = 1; TMR2 = 0xffff; // set to reload immediately ET2 = 1; // enable Timer2 interrupts TR2 = 1; // start Timer2 } //--------------------------------------------------------------------------------// // Initialization of ports I/O // //--------------------------------------------------------------------------------// void portIOInit(void) { P1MDOUT = 0x7F; XBR1 = 0x40; P0 = 0x00; P1 = 0x00; P2 = 0x00; } //------------------------------------------------------------------------------// // Interrupts init // //------------------------------------------------------------------------------// void interruptsInit(void) { IP = 0x20; IE = 0xA0; } //----------------------------------------------------------------------------- // SYSCLK_Init //----------------------------------------------------------------------------- // // This routine initializes the system clock to use the internal 24.5MHz / 8 // oscillator as its clock source. Also enables missing clock detector reset. // void SYSCLK_Init (void) { OSCICN = 0xC3; // configure internal oscillator for // its lowest frequency RSTSRC = 0x04; // enable missing clock detector } //------------------------------------------------------------------------------// // Device init // //------------------------------------------------------------------------------// void deviceInit(void) { // disable watchdog timer PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer SYSCLK_Init(); timerInit(); portIOInit(); interruptsInit(); EA = 1; // enable global interrupts //------------------------------------------------------------------------------// // Main function // //------------------------------------------------------------------------------// void main(void) { _delay1 = 0; _delay2 = 19980; _widthImp = 20; _cDelay = 0; _state = ST_IDLE; deviceInit(); while(1) { }; } }
Алгоритм работы этой функции следующий: запускаем таймер на клики каждые 50 микросекунд. Создаём глобальную переменную _state, которая будет отвечать за текущее состояние контроллера.
По умолчанию мы делаем его равным 0, т.е.
первому состоянию.
Сделаем остальные состояния МК более читабельными с помощью define: #define ST_IDLE 0
#define ST_DELAY_0 1
#define ST_RNT_START 2
#define ST_DELAY_1 3
#define ST_RNT_STOP 4
Смотрим таблицу прерываний в даташите контроллера и обнаруживаем, что прерывание нужного нам таймера имеет вектор (номер) 5. Код, реализующий функцию: //------------------------------------------------------------------------------//
// Timer ISR //
//------------------------------------------------------------------------------//
void timerISR (void) interrupt 5
{
TF2H = 0;
TF2L = 0; // Clear Timer2 interrupt flag
switch(_state)
{
case ST_IDLE:
if (_inputPulse == 0)
{
_state = ST_DELAY_0;
_cDelay = 0;
}
break;
case ST_DELAY_0:
_cDelay++;
if (_cDelay>=_delay1)
{
_state = ST_RNT_START;
_rntStart = ON;
_cDelay = 0;
}
break;
case ST_RNT_START:
_cDelay++;
if (_cDelay >= _widthImp)
{
_state = ST_DELAY_1;
_rntStart = OFF;
_cDelay = 0;
}
break;
case ST_DELAY_1:
_cDelay++;
if (_cDelay >= _delay2)
{
_state = ST_RNT_STOP;
_rntStop = ON;
_cDelay = 0;
}
break;
case ST_RNT_STOP:
_cDelay++;
if (_cDelay >= _widthImp)
{
_state = ST_IDLE;
_rntStop = OFF;
_cDelay = 0;
}
break;
default:
_state = ST_IDLE;
break;
}
Так что же нам делать? При каждом нажатии таймера проверяем состояние МК.
Если он равен 0, проверяем, есть ли на входе сигнал запуска.
Если он существует (inputPulse == 1), мы запускаем последовательность.
Продолжительность задержек между сигналами контролируется количеством щелчков таймера, проверяя его при каждом щелчке в коде обработки состояния.
Когда весь цикл работы завершен, возвращаем МК в состояние 0 и ждем следующего поступающего сигнала.
Прошивка МК компилируется и прошивается довольно просто, из той же IDE нажатием одной кнопки.
Подключаем программатор к плате (как показано в предыдущей статье), включаем питание, нажимаем кнопку «Подключить», затем кнопку «Загрузить код».
Всё, МК прошит. Запустить код на исполнение в МК можно отсюда, нажав кнопку «Go».
Здесь можно установить точки останова и провести с ним сеанс отладки, исследуя результаты на осциллографе.
Кнопки показаны на рисунке и помечены разными цветами.
Заключение
Как видите, не все так сложно при работе с этим МК.Думаю, кому-то этот пост поможет разобраться с этим.
Теги: #кремниевые лаборатории c8051f320 #программирование микроконтроллеров
-
Youtube Запускает Партнерскую Программу
19 Oct, 24 -
Менеджер По Продукту Глазами Разработчиков
19 Oct, 24 -
Сказка Царя Салтана О Потенциале Лапласианца
19 Oct, 24 -
Rbpopup.jquery
19 Oct, 24