Friday, December 28, 2012

Portable console on STM32F407. Prat 3. Coordinate reeding, temperature and battery level from ADS7846.

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

Все больше в интернете появляется статей, о том как обслуживать контроллеры сенсорных экранов. Я расскажу конкретно про контроллер, который использовался в моем проекте - ADS7846. Видел и читал множество статей, о том как считывать координаты, но так и не нашел инструкции как считывать уровень заряда и температуру (эти функции появились в ADS7846 и отсутствуют в предыдущих моделях).

Я уже частично начал рассказ о работе с сенсорным экраном в прошлой части статьи (все конкретно по режимам работы).

STM32 общается с контроллером сенсорного экрана по SPI. Полный запрос вмещается в один байт. Процесс получения данных выглядит: "Открытие диалога", "Последовательная отправка байта запроса", "Получение ответного байта (12/8 бит)", "Завершение диалога".

Содержание "байта запроса"







Описание битов "байта запроса"





















Из описания следует, что седьмой бит (START) должен быть всегда выставлен в 1.

Биты 6-4 (A2-A0) - выбор канала чтения.

Описание битов "байта запроса"












Бит 3 (MODE) управляет длиной ответного пакета данный (0 - 12 бит, 1 - 8 бит).

Бит 2 (SER/DFR) выбор режима (0 - дифференциальный режим, 1 - несимметричность режим).
Говоря практическим языком, если требуется читать координаты - выбирается дифференциальный режим (выставить в 0), а если получить значение батареи или датчика температуры - несимметричный (выставить в 1).


Несимметричный режим.

В несимметричном режиме при обнаружении касания к сенсорному экрану процессор, который управляет ADS7846, пошлет служебный байт, который переведет ADS7846 в режим преобразования. После этого ADS7846 начинает подавать напряжение через встроенные ключи на полевых транзисторах и начнет собирать данные о координатах точки касания, что приведет к увеличению напряжения в точке касания. В течение некоторого времени будут наблюдаться колебания (дребезг), которые через некоторое время затухнут. По истечении времени сбора все внутренние ключи выключатся, и аналого-цифровой преобразователь перейдет в режим преобразования. Если следующий управляющий байт не поступит в течение режима преобразования, то ADS7846 перейдет в режим отключения или в режим ожидания следующей команды. При большой емкости между слоями панели (обычно применяемой для фильтрации помех) требуется выдержать время установления для того, чтобы напряжения, соответствующие паре координат, успели принять стабильные значения. В несимметричном режиме входное напряжение должно установиться не позднее, чем за три тактовых периода до начала формирования слова входных данных, иначе они будут содержать неверные значения.


Дифференциальный режим.

Работа АЦП в дифференциальном режиме похожа на работу в несимметричном режиме, за исключением того, что внутренние ключи должны быть включены от начала сбора данных до окончания преобразования. При преобразовании в дифференциальном режиме напряжение перпендикулярной линии используется в качестве опорного, что позволяет измерять не абсолютное значение напряжения, а коэффициент передачи резистивного делителя. Это означает, что, если напряжение на перпендикулярной линии изменится за счет изменения напряжения источника питания, изменения полного выходного сопротивлении драйвера при изменении его напряжения питания или температуры или изменения полного сопротивления сенсорного экрана из-за изменения температуры, то это изменение будет скомпенсировано за счет работы аналого-цифрового преобразователя в режиме измерения коэффициента передачи.

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

(Ссылка на источник)

Биты 1 и 0 (PD1-PD0) отвечают за введение контроллера сенсорного экрана в различные режимы, в которых у контроллера сенсорного экрана будет разное энергопотребление.

Описание битов выбора режима контроллера


















Процедура записи данных:

static void WR_CMD (uint8_t cmd)
{
   /* Wait for SPI2 Tx buffer empty */
   while (SPI_I2S_GetFlagStatus(Open_SPI, SPI_I2S_FLAG_TXE) == RESET);
   /* Send SPI2 data */
   SPI_I2S_SendData(Open_SPI,cmd);
   /* Wait for SPI2 data reception */
   while (SPI_I2S_GetFlagStatus(Open_SPI, SPI_I2S_FLAG_RXNE) == RESET);
   /* Read Open_SPI received data */
   SPI_I2S_ReceiveData(Open_SPI);
}


Процедура чтения данных:

static int RD_AD(void)

{ 

   unsigned short buf,temp;

   /* Wait for Open_SPI Tx buffer empty */

   while (SPI_I2S_GetFlagStatus(Open_SPI, SPI_I2S_FLAG_TXE) == RESET);

   /* Send Open_SPI data */

   SPI_I2S_SendData(Open_SPI,0x0000);

   /* Wait for SPI2 data reception */

   while (SPI_I2S_GetFlagStatus(Open_SPI, SPI_I2S_FLAG_RXNE) == RESET);

   /* Read Open_SPI received data */

   temp=SPI_I2S_ReceiveData(Open_SPI);

   buf=temp<<8;

   DelayUS(1);

   while (SPI_I2S_GetFlagStatus(Open_SPI, SPI_I2S_FLAG_TXE) == RESET);

   /* Send Open_SPI data */

   SPI_I2S_SendData(Open_SPI,0x0000);

   /* Wait for Open_SPI data reception */

   while (SPI_I2S_GetFlagStatus(Open_SPI, SPI_I2S_FLAG_RXNE) == RESET);

   /* Read Open_SPI received data */

   temp=SPI_I2S_ReceiveData(Open_SPI);

   buf |= temp;

   buf>>=3;

   buf&=0xfff;

   return buf;

} 



Процедура получения координаты X:

int Read_X(void)

{  

   int i;

   TP_CS(0);

   DelayUS(1);

   WR_CMD(0x90);

   DelayUS(1);

   i=RD_AD();

   TP_CS(1);

   return i;

}



Процедура получения координаты Y:

int Read_Y(void)

{

   int i;

   TP_CS(0);

   DelayUS(1);

   WR_CMD(0xD0);

   DelayUS(1);

   i=RD_AD();

   TP_CS(1);

   return i;

} 



Процедура получения текущего уровня заряда:

int Read_Bat(void)

{

   int i;

   TP_CS(0);

   DelayUS(1);

   WR_CMD(0xa4);

   DelayUS(1);

    i=RD_AD();

   TP_CS(1);

   return i;

}



Ссылки на части статьи проекта:

Портативная консоль на STM32F407. Часть 1
Портативная консоль на STM32F407. Часть 2. Питание от батареи.

1 comment :

  1. Иван, поделитесь исходником? Меня интересует инициализация ili9481?
    Пишите на почту: eu7abz@tut.by

    ReplyDelete