Подключение кнопок управления магнитолой по CAN



Не редкость, что на автомобилях выходят из строя штатные мультимедийные системы,
особенно если в них используются многодисковые CD-чейнджеры. Стоимость ремонта или замены такого неисправного устройства может составлять большую сумму.
Иногда целесообразнее приобрести переходную рамку и установить современную мультимедийную систему(далее МС), недорогую и гораздо более функциональную.


Читать дальше

STM32 + Параллельная NAND Flash + файловая система Yaffs. Часть первая


Как часто приходится жалеть о принятых решениях. Безрассудно прожитые школьные годы, неверно выбранный ВУЗ, разгульная студенческая жизнь, переезд не в тот город, выбор параллельной NAND Flash в качестве вместилища архивных данных.
Вот казалось бы, интерфейс EMC есть, команды у флешки для записи/чтения простые, как угол дома и самое главное — дешево! Кто-то может возразить, сказав, что обычные SD-карты сегодня тоже дешевые и разъемы к ним недорогие, плюс по софту тоже все готово — тут тебе и файловая система FATFs, и примеры. Но иногда в такой разговор может вмешаться слишком «умный» программист, который скажет:
— Нет! Мы делаем промышленный прибор, который будет подвержен тряскам во время транспортировки, кривым рукам наладчиков на объекте, вибрациям в процессе работы. Никаких разъемов для критически важных узлов.
На что вы возможно ответите:
— Тогда может быть использовать память с интерфейсом SPI, там вроде как тоже давно все изведанно.
— Нет, нет! Дорого, да и чем плоха NAND'а? — очень самоуверенно возражает оппонент.
— Ну я не уверен насчет…
— Бла, бла, бла! Поверьте я знаю что предлагаю, нам нужна параллельная NAND flash.
— Ну Вы не сомневаетесь, что по софту не будет проблем?
— Кто сомневается?! Я сомневаюсь?!!!
— Ладно, ладно, дерзайте, — махнете Вы рукой.
Микросхема будет заложена в решение, и пути назад уже не будет…


Читать дальше

ОС как библиотека

Иногда внезапно возникает необходимость сделать какую-то работу в коде программы в синхронном режиме — то есть, не конечным автоматом, а просто дожидаясь результата каких-то действий. Например, скачать http-страничку, или, того хуже, https-страничку.

Но и тормозить основной цикл тоже как-то не очень хорошо. На этот случай есть известное решение — ОС.

Но если требуется допилить уже существующий проект с минимальным вмешательством в остальной код?
Вот мне стало интересно сделать мини-ОС, которая подключается к проекту как библиотека. То есть, делаем вызов какой-нибудь функции os_Init() и получаем возможность создавать потоки, не вмешиваясь в работу основного цикла. Он продолжает работать, как будто никакой ОС и нет, просто иногда управление передаётся дополнительным потокам.



Читать дальше

STM32 - входим в bootloader по кнопке.

Лирическое отступление.

Года 4 назад начались у нас продажи мелких партий устройств, основанных на STM32. Так как на само устройство мы, в виду миниатюрности устройства, не ставили разъём под программирование, то заливать прошивку был решено используя родной bootloader. Но тут опять возникла проблема — как в bootloader входить. Замыкать ножку BOOT при помощи джампера показалось плохой идеей. И тогда была поставлена задача — контроллер должен входить в bootloader по нажатию 1й кнопки.


Читать дальше

Ещё один программный таймер

Решил тоже поучаствовать в конкурсе «у кого таймер проще» :)
Это даже не велосипед, а так, самокат :)

Времени расписывать особо нет, поэтому буду краток.
Да и пояснять особо нечего.
typedef enum eTimerStatus
{
	etsTimerIDLE = 0,
	etsTimerCount,
	etsTimerEvent
} eTimerStatus;

typedef struct stTimer
{
	volatile ShortTimer *Count;
	volatile eTimerStatus Status;
} stTimer;

Это базовые определения. Теперь функционал:

#include "Timers.h"

/**
*	\brief Пул таймеров
*/
static ShortTimer volatile TimersPool[eTimersNumber];
static eTimerStatus volatile TimersStatusPool[eTimersNumber];

void TickTimers()
{
	for(int i=0; i < eTimersNumber; i++)
	{
		if(TimersPool[i] > 0)
		{
			TimersPool[i] --;
			if(0 == TimersPool[i])
			{
				TimersStatusPool[i] = etsTimerEvent;
			}
		}
	}
}

void StartTimer(eTimerIndex timer, ShortTimer period_ms)
{
	TimersPool[timer] = period_ms;
	TimersStatusPool[timer] = etsTimerCount;
}

eTimerStatus GetTimerStatus(eTimerIndex timer)
{
	if(etsTimerEvent == TimersStatusPool[timer])
	{
		TimersStatusPool[timer] = etsTimerIDLE;
		return(etsTimerEvent);		
	}
	else
	{
		return(TimersStatusPool[timer]);
	}
}

ShortTimer GetTimerCount(eTimerIndex timer){
	return(TimersPool[timer]);
}


Ну и пример использования.
typedef unsigned int ShortTimer;

typedef enum eTimerIndex
{
	eADC1Timer = 0,
	eADC2Timer,
	eADC3Timer,
	eADCProcessTimer,
	eChanDiapSwitchDelayTimer,
	eModbusTimer,
	eTimersNumber
} eTimerIndex;

void SysTick_Handler(void){

	TickTimers();
}

void main(){
    ...
    StartTimer(eADCProcessTimer, 5);

    while (1){
	...
	if(etsTimerEvent == GetTimerStatus(eADCProcessTimer)){
	    ProcessADC();
	    StartTimer(eADCProcessTimer, 5);
	}
        ...
    }
}


Если что непонятно (что вряд ли), спрашивайте, добавлю.
Главное удобство в простоте использования. Нужен ещё один таймер — добавили имя в enum eTimerIndex и можно пользоваться.

PS: Сейчас глянул ещё раз — а зачем мне вообще stTimer? Наверно, изначально что-то другое задумывал. Ну да ладно.

Анализатор протокола WS2812b для Saleae LLC

После приобретения клона анализатора Saleae, стало интересно, можно ли реализовать свой анализатор сигнала (плагин), что и было сделано на примере реализации анализатора протокола WS2812b. Остальное под катом.


Читать дальше

STM32F030F4 инициализируем ADC

ADC на PA0

Инициализация:
void ADC_Config(void)
{
  ADC_InitTypeDef     ADC_InitStructure;
  GPIO_InitTypeDef    GPIO_InitStructure;

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  ADC_DeInit(ADC1);
  
  ADC_StructInit(&ADC_InitStructure);
  
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
  ADC_Init(ADC1, &ADC_InitStructure); 
  
  ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_239_5Cycles);
  ADC_GetCalibrationFactor(ADC1);
  ADC_Cmd(ADC1, ENABLE);     
  
  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY)); 
  
  ADC_StartOfConversion(ADC1);
}


Использование:

ADC_Config();
while(1) {
    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
    ADCValue = ADC_GetConversionValue(ADC1);
}


Вместо ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; можно написать ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;, тогда перед каждой оцифровкой надо будет вызывать ADC_StartOfConversion(ADC1);

Заодно есть вопрос. Подключаю PA0 через делитель к +3.3V, гоняю по циклу ADC_GetConversionValue(). Оцифрованые значения имеют разбежку +/-10. Это нормально поведение АЦП или я что-то не так делаю?

STM32F030F4 инициализируем USART

Набросаю к себе полезных снипетов для STM32F030F4, чтобы самому не забыть и кому-нибудь надеюсь пригодится.

Инициализация USART




Читать дальше

Bluetooth Smart Broadcaster на RSoC фирмы Cypress

Эта вводная статья по тематике является продолжением моей статьи [2]. Здесь я расскажу о разработке микромощного BLE (Bluetooth Low Energy) устройства, или как их сейчас принято называть, Bluetooth Smart. Устройство выполняет функцию маяка и построено на модуле CYBLE-022001-00 фирмы Cypress Semiconductor.




Читать дальше
  • +6
  • 07 января 2016, 01:04
  • Ser60

Стек для W5200 без циклов задержек + STM32F103

Чипы корейской фирмы WIZnet весьма широко известны и популярны. Так же полно где можно скачать драйверы для этих микросхем. Последняя реализация выполнена на W5500 здесь
Однако все драйверы построены по принципу вызова функций, которые весьма надолго стопорят основной цикл программы, мучительно и многократно ожидая события от внешней системы. Особенно «умиляет» ожидание в функции отправки по TCP и выход из нее по Timeout. А ведь это может растянуться не на одну секунду, и даже не 10! (При стандартных настройках — 28 сек). В некоторых случаях, если программа заточена полностью на Ethernet — это не критично, но не в моем случае. Да и вообще, инструкции вида
while(!Внешнее событие);
меня вымораживает напрочь, так как устройство полностью оказывается неработоспособным длительное время.
Мною были написаны несколько модулей, в которых я реализовал стек для W5200 без задержек.

Читать дальше
  • +5
  • 26 декабря 2015, 22:52
  • Mihail
  • 1