Как стать автором
Обновить

Продолжение истории про «Сердце» электронного устройства или простейшее программирование Silicon Labs C8051F320

Время на прочтение6 мин
Количество просмотров18K
Не так давно я написал статью про мою поделку на основе микроконтроллера Silicon Labs C8051F320. Пришло время рассказать и про программирование данного мк под простейшие задачи.
image

Подробности под катом.


Итак, в предыдущей статье я рассказал о небольшой платке, которая должна стать основой будущего устройства. На ней расположен сам микроконтроллер и его небольшая обвеска, предназначенная для ресета прошивки, питания мк и т.д. Одной из задач, которую данное устройство должно было выполнять у нас на работе, было управление некоторыми устройствами на исследовательском стенде. Так как по сути задача была не шибко сложной, то и прошивка для мк не требовала каких либо сложных решений наподобие работы с USB и прочими специфичными штуками, но разбор этой прошивки может в будущем хорошо помочь тем, кому придется работать с подобным мк по учебе (у моего друга вроде как сейчас по учебе идет программирование 51го ядра) или по работе. Но обо всем по порядку.

Задача


Задачу поставили довольно несложную — организовать простейшее включение/выключение удаленных устройств от микроконтроллера, организовав необходимые задержки между срабатываниями. В теории, надо было еще сделать управление этими задержками с ПК через USB, но, как оказалось потом, это не так важно.

Аппаратная часть


Для решения данной задачи нужна была реализация апаратной части устройства, отвечающео за сопряжение мк с удаленными устройствами, так как само «сердце» ничего такого на борту не несло, да и изначально оно расчитывалось на уравление периферийной платой. Особо зацикливаться на аппаратной части не буду, так как статья про прошивку, но все же для полноты картины представлю ее схему и краткое описание.

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



Убедившись, что никаких изменений в устройстве не предполагается, а точнее уточнив у начальства, что не будет всяких там «Ой, а давайте-ка...», после которых придется делать совершенно новую схему, мы приступили к изготовлению печатной платы. Про отсутствие денег я уже говорил, так что всего лишь скажу, что делалось все из подручных элементов — плата травилась у нас же на коленке из куска старого текстолита, элементы нашлись в кладовке. В общем, полная разруха. НИИ, что еще сказать… В общем, результат виден на фото:





К слову, потом все же случилось «Ой, а давайте-ка...», поэтому пришлось клепать пару мелких платок, резать дорожки на этой и все это соплями соединять, но пост не об этом.

Программная часть

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

Алгоритм работы

Алгоритм прост как валенок:
  • Проверяем наличие внешнего сигнала «Старт» от вышестоящего устройства
  • Если сигнал получен — отрабатываем заданную последовательность, наплевав на проверку срабатывания устройств. К слову, этот метод показался мне не совсем корректным, поэтому все же одну проверку я сделал, чтоб не бабахнуло, но реализовал ее просто аппаратно, а не в прошивке.
  • Возвращаемся в пункт первый


Алгоритм выбран, аппататная часть готова, приступаем ко конфигурированию и программизму микроконтроллера.

Конфигурирование микроконтроллера

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





В процессе настройки МК нам нужно будет настроить его порты ввода/вывода, чтоб в исходном состоянии на них был логический ноль, настроить таймер-счетчик на нужный нам интервал (ЕМНИП я ставил 50 микросекунд), включить прерывания от таймера и еще по мелочи. Точно я все не помню, делал давно, покажу просто пример. В меню Properties выбираем нужный нам пункт и видим октрывшееся окно, где все необходимые нам параметры настраиваются в GUI.



При нажатии ОК все настройки копируются в окно с кодом. Настроили МК, но не спешим закрывать конфигуратор, он там еще понадобится. Качаем с того же сайта Silicon Labs IDE, с помощью которой и будем прошивать МК. Запускаем ее.

Тут есть один нюанс, ей нужно подсунуть компилятор от Keil С51, чтобы она его использовала. Не буду на этом зацикливаться, просто покажу картинкой как это делается. Открываем меню Project — Tool Chain Integration и указываем пути к компиляторам кейля.



Открываем конфигуратор и копируем из него получившийся код в 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 нажатием одной кнопки. Подключаем программатор к плате (как — показано в предыдущей статье), включаем питание, жмем кнопку «Подключиться», потом кнопку «Download code». Все, МК прошит. Запустить код на выполнение в МК можно отсюда же, нажав кнопку «Go». Здесь же можно расставить точки останова и провести с ним сеанс дебага, рассматривая результаты на осциллографе.


Кнопки показаны на рисунке и подписаны разными цветами.

Заключение



Как видите, не все так сложно при работе с данным МК. Думаю, что кому-нибудь этот пост поможет с ним разобраться.
Теги:
Хабы:
Всего голосов 7: ↑6 и ↓1+5
Комментарии0

Публикации