Например TDA7294

Форум РадиоКот • Просмотр темы - STM32 сенсорные кнопки
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Вт апр 23, 2024 22:15:50

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 7 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: STM32 сенсорные кнопки
СообщениеДобавлено: Чт дек 26, 2013 14:34:12 
Опытный кот
Аватар пользователя

Карма: 16
Рейтинг сообщений: 170
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 827
Откуда: Уже не город Белых гор
Рейтинг сообщения: 3
Делаю я тут клавиатуру для прибора. И грустно мне стало использовать мембранную клавиатуру, когда в моём микропроцессоре есть нативный контроллер сенсорных кнопок.
Информации по этому вопросу довольно мало. С одной стороны, есть библиотека от ST. Но она громоздкая и для моих задач излишняя.
С другой стороны, есть возможность прямо работать с регистрами контроллера. Нашёл в сети маленький примерчик, и на его основе делаю свой интерфейс.
Выкладываю наработки.
Условия: работа во FreeRTOS, процессор STM32F051.
Код пока не проверен, так как плата с сенсорными кнопками в процессе изготовления.
Инициализация:
Код:
void __inline vInit_TSC (void)
{   
// включаю тактирование блока сенсорных кнопок
   RCC->AHBENR |= RCC_AHBENR_TSEN | RCC_AHBENR_GPIOAEN;   

// настройка портов IO
   GPIOA->MODER |= GPIO_MODER_MODER4_1;      // PA4 - вход кнопки
   GPIOA->OTYPER &= ~GPIO_OTYPER_OT_4;         // пин PA4 - пуш пулл
   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR4;   // скорость пина 50 МГц
   GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR4;         // пин без подтяжки

   GPIOA->MODER |= GPIO_MODER_MODER5_1;      // PA5 - вход кнопки
   GPIOA->OTYPER &= ~GPIO_OTYPER_OT_5;         // пин PA5 - пуш пулл
   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5;   // скорость пина 50 МГц
   GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR5;         // пин без подтяжки

   GPIOA->MODER |= GPIO_MODER_MODER6_1;      // PA6 - вход кнопки
   GPIOA->OTYPER &= ~GPIO_OTYPER_OT_6;         // пин PA6 - пуш пулл
   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6;   // скорость пина 50 МГц
   GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR6;         // пин без подтяжки

   GPIOA->MODER |= GPIO_MODER_MODER7_1;      // PA7 - вход конденсатора
   GPIOA->OTYPER |= GPIO_OTYPER_OT_7;         // пин PA7 - открытый сток
   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7;   // скорость пина 50 МГц
   GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR7;         // пин без подтяжки

   GPIOB->MODER |= GPIO_MODER_MODER11_1;      // PB11 - вход кнопки
   GPIOA->OTYPER &= ~GPIO_OTYPER_OT_11;      // пин PB11 - пуш пулл
   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR11;   // скорость пина 50 МГц
   GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR11;      // пин без подтяжки

   GPIOB->MODER |= GPIO_MODER_MODER12_1;      // PB12 - вход кнопки
   GPIOA->OTYPER &= ~GPIO_OTYPER_OT_12;      // пин PB12 - пуш пулл
   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR12;   // скорость пина 50 МГц
   GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR12;      // пин без подтяжки

   GPIOB->MODER |= GPIO_MODER_MODER13_1;      // PB13 - вход кнопки
   GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13;      // пин PB13 - пуш пулл
   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR13;   // скорость пина 50 МГц
   GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR13;      // пин без подтяжки

   GPIOB->MODER |= GPIO_MODER_MODER14_1;      // PB14 - вход конденсатора
   GPIOA->OTYPER |= GPIO_OTYPER_OT_14;         // пин PB14 - открытый сток
   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR14;   // скорость пина 50 МГц
   GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR14;      // пин без подтяжки
   
   GPIOA->AFR[0] |= GPIO_AFRL_AFRL4 & (GPIO_AF_AF3 << 16);      // PA4 - слайдер 1
   GPIOA->AFR[0] |= GPIO_AFRL_AFRL5 & (GPIO_AF_AF3 << 20);      // PA5 - слайдер 2
   GPIOA->AFR[0] |= GPIO_AFRL_AFRL6 & (GPIO_AF_AF3 << 24);      // PA6 - слайдер 3
   GPIOA->AFR[0] |= GPIO_AFRL_AFRL7 & (GPIO_AF_AF3 << 28);      // PA7 - конденсатор
   GPIOB->AFR[1] |= GPIO_AFRH_AFRH3 & (GPIO_AF_AF3 << 12);      // PB11 - кнопка BACK
   GPIOB->AFR[1] |= GPIO_AFRH_AFRH4 & (GPIO_AF_AF3 << 16);      // PB12 - кнопка STOP
   GPIOB->AFR[1] |= GPIO_AFRH_AFRH5 & (GPIO_AF_AF3 << 20);      // PB13 - кнопка ENTER
   GPIOB->AFR[1] |= GPIO_AFRH_AFRH6 & (GPIO_AF_AF3 << 24);      // PB14 - конденсатор
   
// настройка контроллера сенсорных кнопок   
   TSC->CR = (1 << TSC_CR_TSCE);   // разрешить контроллер

   TSC->CR =
        (2 << TSC_CR_CTPH)
      | (6 << TSC_CR_CTPL)
      | (9 << TSC_CR_SSD)
      | (0 << TSC_CR_SSE)
      | (1 << TSC_CR_SSPSC)
      | (0 << TSC_CR_PGPSC)
      | (TSC_CR_MCV_16383 << TSC_CR_MCV)
      | (0 << TSC_CR_IODEF)
      | (0 << TSC_CR_SYNCPOL)
      | (0 << TSC_CR_AM)
      | (0 << TSC_CR_START)
      | (1 << TSC_CR_TSCE);

   TSC->IER =
        (1 << TSC_IER_EOAIE)      // прерывание по окончании измерения
      | (1 << TSC_IER_MCEIE);      // прерывание по переполнению

   TSC->IOSCR = TSC_IOSCR_G2_IO4   // конденсатор PA7 (G2_IO4)
      | TSC_IOSCR_G6_IO4;         // конденсатор PB14 (G6_IO4)

   TSC->IOCCR = TSC_IOCCR_G2_IO1   // кнопка PA4
      | TSC_IOCCR_G6_IO1;         // кнопка PB11
//      | TSC_IOCCR_G2_IO2         // кнопка PA5
//      | TSC_IOCCR_G2_IO3         // кнопка PA6
//      | TSC_IOCCR_G6_IO1         // кнопка PB11
//      | TSC_IOCCR_G6_IO2         // кнопка PB12
//      TSC_IOCCR_G6_IO3;         // кнопка PB13
// в процессе измерения учавствует только одна кнопка из группы
      
   TSC->IOGCSR = TSC_IOGCSR_G2E   // разрешить группу 2
      | TSC_IOGCSR_G6E;         // разрешить группу 6
}

Я использовал 6 кнопок в двух группах. Видно по комментариям.
В обработчике прерывании я измеряю емкость всех кнопок, а затем передаю массив на обработку:
Код:
/*
Программа обработчика прерывания контроллера TS
Запускается снаружи установкой бита TSC->CR |= (1 << TSC_CR_START);
и при конфигурации разрешения первых кнопок в группах
Программа измеряет значения ёмкости всех шести кнопок в двух группах и
выдаёт результат в массиве. Значение ёмкости = 0 определяет ошибку измерения
Результат передаётся через очередь RTOS в обработчик клавиатуры
*/

void TS_IRQHandler (void)
{
   portBASE_TYPE    xWoken = pdFALSE;
   Tsense          *point_t = &t;
      
   if ((TSC->ISR & TSC_ISR_MCEF)               // переполнение счётчика
   {
      t.Cap[0][t.Position] = 0;               // записали ошибку измерения
      t.Cap[1][t.Position] = 0;
      TSC->ICR = TSC_ICR_MCEIC | TSC_ICR_EOAIC;   // снять флаг переполнения и окончания
   }
   else
   {      
      t.Cap[0][t.Position] = *TS_Group[0];      // прочитали значение ёмкости
      t.Cap[1][t.Position] = *TS_Group[1];
      TSC->ICR = TSC_ICR_EOAIC;               // снять флаг окончания   
   }
      
   if (++t.Position < TS_MAX_NUM_PIN)            // если измерили не все кнопки, продолжить
   {
      TSC->IOCCR = TS_Mask_Channel[0][t.Position]
         | TS_Mask_Channel[0][t.Position];      // определить маску следующих кнопок
      TSC->CR |= (1 << TSC_CR_START);            // запустить измерение следующих кнопок
      t.EndMeasure = 0;                     // сбросить флаг окончания
   }
   else                                 // если измерение окончено, передать структуру
   {
      t.Position = 0;                        // подготовить указатель
      t.EndMeasure = 1;                     // выставить флаг окончания
      xQueueSendToBackFromISR (g.xTS_Queue, &oint_t, &xWoken);
      portYIELD_FROM_ISR (xWoken);
   }
}

Структура данных кнопок:
Код:
#define   TS_MAX_NUM_GROUP   2
#define   TS_MAX_NUM_PIN   3

#pragma pack(4)
typedef struct Tsense
{
   int      Cap [TS_MAX_NUM_GROUP][TS_MAX_NUM_PIN];      // массив значений ёмкости кнопок
   int      Position;      // номер кнопки
   int      EndMeasure;      // флаг окончания измерения
}Tsense;
#pragma pack()

extern Tsense t;

// массив указателей на регистры счётчиков групп
const __IO uint32_t *TS_Group [TS_MAX_NUM_GROUP] =
{
   &TSC->IOGXCR[1],
   &TSC->IOGXCR[5]   
};
// массив масок разрешения кнопок в группе
const uint32_t TS_Mask_Channel [TS_MAX_NUM_GROUP] [TS_MAX_NUM_PIN] =
{
   TSC_IOCCR_G2_IO1, TSC_IOCCR_G2_IO2, TSC_IOCCR_G2_IO3,
   TSC_IOCCR_G6_IO1, TSC_IOCCR_G6_IO2, TSC_IOCCR_G6_IO1   
};

И, наконец, главный цикл программы. Здесь пока рыба, а будет обработка
Код:
/*
Задача обработки значений сенсорных кнопок
*/      
void vTsense (void *pvParameters)
{
   int    i, j;
   Tsense   *Sense;
   int      TSC_min [TS_MAX_NUM_GROUP][TS_MAX_NUM_PIN];
   int      TSC_max [TS_MAX_NUM_GROUP][TS_MAX_NUM_PIN];
   
   vInit_TSC ();
   
// обнулить данные в структуре кнопок
   for (i = 0; i < TS_MAX_NUM_GROUP; i++)
   {
      for (j = 0; j < TS_MAX_NUM_PIN; j++)
      {
         TSC_max[i][j] = t.Cap[i][j] = 0;
         TSC_min[i][j] = 16384;            // максимальное значение
      }
   }
   t.Position = t.EndMeasure = 0;   // начальные значения указателей
   for ( ; ; )
   {
      vTaskDelay (200);
      TSC->CR |= (1 << TSC_CR_START);            // запустить измерение
// из очереди получаем указатель на структуру ёмкостей, ждём до посинения
      xQueueReceive (g.xTS_Queue, &Sense, portMAX_DELAY);
      if (t.EndMeasure)         // для случая небесконечного ожидания
      {
         t.EndMeasure = 0;   
         vTSCompareminmax (&Sense->Cap[0][0], TSC_min, TSC_max);
// для начала просто выведу значение емкости
      }
   }
}

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


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32 сенсорные кнопки
СообщениеДобавлено: Чт дек 26, 2013 18:05:13 
Опытный кот
Аватар пользователя

Карма: 3
Рейтинг сообщений: 43
Зарегистрирован: Вт апр 12, 2011 18:38:19
Сообщений: 838
Откуда: с Земли
Рейтинг сообщения: 0
Дружище, очень интересен Ваш проект! Я делал touch клавиатуру на AT42QT2160, результат получился неплохой - работало через оргстекло 2мм. Пришлось немного повозиться с платой. Пишите все, что накопаете, интересно не столько программное решение, как ньюансы трассировки платы, а также материал и толщина панели. Просто у меня есть готовое решение, но хочется сделать "все-в-одном" - контроллер клавиатуры и LCD дисплея.
Заранее спасибо.

_________________
Все будет только лучше, в крайнем случае - хуже.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32 сенсорные кнопки
СообщениеДобавлено: Пн дек 30, 2013 22:57:26 
Опытный кот
Аватар пользователя

Карма: 16
Рейтинг сообщений: 170
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 827
Откуда: Уже не город Белых гор
Рейтинг сообщения: 0
Немного результатов.
Всё запустилось. Наступал на грабли. Как свои по невнимательности, так и послушался глупых советов от STM.
Сенсорные кнопки уверенно работают через стеклотекстолит 1,5мм со шлейфом 20 см на шилд Дискавери.
Показания счётчиков плывут от времени по причине нестабильности конденсаторов и геометрии шлейфа.
Применил фильтрацию сигналов - всё отлично заработало.
Пока реализован вариант с отдельными кнопками.
Вторым этапом буду мучить слайдер - хочу получить данные в виде линейного указателя 0-100%


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: STM32 сенсорные кнопки
СообщениеДобавлено: Пт янв 03, 2014 16:17:53 
Опытный кот
Аватар пользователя

Карма: 16
Рейтинг сообщений: 170
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 827
Откуда: Уже не город Белых гор
Рейтинг сообщения: 0
Поработал над ошибками. Результаты вполне стабильные.
Привожу картинку анализа работы программы обработки значений кнопок
Изображение
Я выводил текущие значения переменных в терминал, а затем анализировал в Экселе. Ну и подписал графики в графическом редакторе.
Самый верхний график - отфильтрованное максимальное значение счётчика контроллера кнопок. Максимальное значение получается при минимальной ёмкости кнопки.
Видно, как при нажатии на кнопку уменьшается значение счётчика - увеличивается ёмкость кнопки (через текстолит 1,5 мм)
У меня есть переменная, которая отслеживает максимальное изменение ёмкости кнопки. Относительно этой переменной определяется порог срабатывания счётчика антидребезга. Как только счётчик досчитал до определённой величины - изменяется состояние кнопки. Она считается нажатой. После отпускания также считает счётчик антидребезга отпускания. Если досчитал до порога - кнопка считается отжатой. Это стандартный антидребезг. А вот над функциями фильтрации сигналов и порогами срабатывания пришлось поэкспериментировать.
Чтобы остальные не наступали на самые грабельные грабли, подскажу один неявный момент:
У меня при измерении ёмкости трёх датчиков одного и того же канала был странный глюк. Первый канал давал стабильные показания, а два других прыгали случайным образом на 3-10%. После трёхдневных поисков выяснилось, что после измерения одного канала и переключения регистра маски канала
Код:
TSC->IOCCR = TS_Mask_Channel;

и перед следующим измерением
Код:
TSC->CR |= (1 << TSC_CR_START);

обязательно нужна задержка для разрядки конденсаторов.
Я просто применил цикл на 40 тактов.


Вернуться наверх
 
Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: STM32 сенсорные кнопки
СообщениеДобавлено: Пт янв 03, 2014 16:43:45 
Опытный кот
Аватар пользователя

Карма: 3
Рейтинг сообщений: 43
Зарегистрирован: Вт апр 12, 2011 18:38:19
Сообщений: 838
Откуда: с Земли
Рейтинг сообщения: 0
Спасибо за опыт!

_________________
Все будет только лучше, в крайнем случае - хуже.


Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: STM32 сенсорные кнопки
СообщениеДобавлено: Пт апр 11, 2014 11:45:56 
Первый раз сказал Мяу!
Аватар пользователя

Зарегистрирован: Вт авг 27, 2013 10:51:04
Сообщений: 31
Откуда: Донецк, Украина
Рейтинг сообщения: 0
А можно взглянуть на саму схему?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32 сенсорные кнопки
СообщениеДобавлено: Вт апр 15, 2014 17:52:01 
Опытный кот
Аватар пользователя

Карма: 16
Рейтинг сообщений: 170
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 827
Откуда: Уже не город Белых гор
Рейтинг сообщения: 0
evilbob писал(а):
А можно взглянуть на саму схему?

Схема из даташита, там два конденсатора и резисторы на ножках.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 7 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 29


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y