Простенькие часики на MSP430

    Начитавшись огромным количеством статей про Arduino/LaunchPad захотелось приобрести подобную игрушку. Выбор пал на MSP430, так как его цена намного более привлекательна для старта в мир микроконтроллеров.
    После томительных 5 дней ожидания, волшебная коробочка оказалась в моих руках. Поиграв минут 10 со светодиодами, захотелось сделать что-нибудь более интересное… Например часики!



    Под рукой оказался старенький Siemens A65, который стал донором для моего небольшого проекта. Вытаскиваем из него экранчик и думаем, как бы его подключить. После недолго гугления, я успешно попал на ветку форума РадиоКот, где обсуждались распиновки и инициализации экранов. Если кто сталкивался с задачей подключения экранчиков к микроконтроллеру то знает, что мало узнать схему подключения, так как в экране стоит контроллер, для общения с которым нужно знать команды. Например для включения экрана и отображения мусора из памяти, некоторым контроллерам нужно послать несколько десятков команд, а некоторым хватает и меньше 10. Так вот, зачастую даташиты на контроллеры не найти, и в таком случае помогает только считывание инициализации экрана во время его работы на телефоне. Но мне повезло, инициализацию и команды для моего экранчика (в моем случае LPH8731-3C c контроллером EPSON S1D15G14) не только разобрали, но и даже нашелся на него даташит.

    И так, смотрим распиновку, припаиваем проводки и подключаем к микроконтроллеру.

    Распиновка для LPH8731-3C

    Распиновка для LPH8731-3C. (Взято с форума РадиоКот)
    Где:
    • CS — Chip Select. Когда находится в состоянии Low, чип готов принимать информацию.
    • RESET — ножка для сброса контроллера. Сигналом сброса служит переход из High -> Low -> High (по спецификации контроллера минимальное время 5мс).
    • RS — Служит для определения типа передаваемых данных (в даташите и у меня обозначается как CD). Для отправки команды должен быть в состоянии Low, для передачи данных — High.
    • CLK — служит тактовым сигналом для передачи данных.
    • DAT — для передачи данных.
    • VDD — по спецификации от +1.6V до +3.6V.
    • GND — надеюсь вы сможете сами угадать?;)
    • LED_A — оба разъема для подачи питания на подсветку. Тут лучше давать напряжение через резистор (можно без него, но в моем случае один из светодиодов начинал перегреваться, от чего получался засвет на экране).
    • LED_K — это к GND.

    Кстати, некоторые уже могли заметить, что тут для передачи данных используется SPI, так что CLK и DAT можно подключить к SPI пинам MSP430.


    Заводим «шарманку»



    Теперь надо разобраться, как же общаться с контроллером. Для контроллера экрана существует 2 типа принимаемых данных — команда или данные. Для выбора типа данных используется отдельный пин. В остальном же, процедура передачи данных одинакова.

    Процедура передачи данных на контроллер, взятая из даташита. Тут почему-то не указано состояние пина RS/CD. Кстати, если во время передачи данных состояние CS изменится Low -> High, прием данных приостановится. А вот в конце передачи данных, дергать CS вверх не обязательно (но рекомендуется).

    Немного злобного кода
    Код приведен для CSS (TI's Code Composer Studio).
    Тут он не полностью, а только кусками для примера. Комментарии на английском, так как мне больше нравится так:)

    LPH87313C.h
    /**********************************************************/
    /*		Pins and outputs								  */
    /**********************************************************/
    // Chip Select line		pin1.0
    #define LCD_CS BIT7
    #define LCD_CS_DIR P1DIR
    #define LCD_CS_OUT P1OUT
    
    // Hardware Reset		pin1.1
    #define LCD_RESET BIT6
    #define LCD_RESET_DIR P1DIR
    #define LCD_RESET_OUT P1OUT
    
    // Command/Data mode line	pin1.4
    #define LCD_CD BIT3
    #define LCD_CD_DIR P1DIR
    #define LCD_CD_OUT P1OUT
    
    // SPI
    #define SPI UCA0TXBUF
    


    LPH87313C.с
    void LCD_SendCmd(unsigned char Cmd)
    {
    	LCD_CS_OUT |= LCD_CS; // set CS pin to High
    	LCD_CD_OUT &= ~LCD_CD; // set CD pin to Low
    	LCD_CS_OUT &= ~LCD_CS;
    
    	SPI = Cmd;
    }
    
    void LCD_SendDat(unsigned char Data)
    {
    	LCD_CD_OUT |= LCD_CD; // set CD pin to High
    
    	SPI = Data;
    }
    



    Теперь мы знаем, как отправить данные на контроллер (ну или хотя бы имеем представление). К счастью в даташите не только описаны все команды, но и имеется даже пример первоначальной инициализации экрана. В целом ее можно разделить на 3 этапа: делаем ресет контроллера (hardware & software reset), задаем первоначальную настройку параметров, включаем дисплей.

    А тут много отправляемых команд
    В принципе большинство параметров задаются как есть, но некоторые вещи можно менять. Например то, в каком порядке будут записываться значения в память (сверху вниз — справа налево/ снизу вверх — справа налево/ и тд), контраст, а так же глубина цвета (256 цветов или 4096).

    LPH87313C.с
    void LCD_Init()
    {
    	// Set pins to output direction
    	LCD_CS_DIR |= LCD_CS;
    	LCD_RESET_DIR |= LCD_RESET;
    	LCD_CD_DIR |= LCD_CD;
    
    	LCD_CS_OUT &= ~LCD_CS;
    	LCD_RESET_OUT &= ~LCD_RESET;
    	LCD_CD_OUT &= ~LCD_CD;
    
    	__delay_cycles(160000); //wait 100ms (F_CPU 16MHz)
    	LCD_RESET_OUT |= LCD_RESET;
    	__delay_cycles(160000);
    
    	LCD_SendCmd(0x01); //reset sw
    	__delay_cycles(80000);
    
    	LCD_SendCmd(0xc6); //initial escape
    	LCD_SendCmd(0xb9); //Refresh set
    	LCD_SendDat(0x00);
    
    	__delay_cycles(160000);
    
    	LCD_SendCmd(0xb6); //Display control
    	LCD_SendDat(0x80); //
    	LCD_SendDat(0x04); //
    	LCD_SendDat(0x0a); //
    	LCD_SendDat(0x54); //
    	LCD_SendDat(0x45); //
    	LCD_SendDat(0x52); //
    	LCD_SendDat(0x43); //
    
    	LCD_SendCmd(0xb3); //Gray scale position set 0
    	LCD_SendDat(0x02); //
    	LCD_SendDat(0x0a); //
    	LCD_SendDat(0x15); //
    	LCD_SendDat(0x1f); //
    	LCD_SendDat(0x28); //
    	LCD_SendDat(0x30); //
    	LCD_SendDat(0x37); //
    	LCD_SendDat(0x3f); //
    	LCD_SendDat(0x47); //
    	LCD_SendDat(0x4c); //
    	LCD_SendDat(0x54); //
    	LCD_SendDat(0x65); //
    	LCD_SendDat(0x75); //
    	LCD_SendDat(0x80); //
    	LCD_SendDat(0x85); //
    
    	LCD_SendCmd(0xb5); //Gamma curve
    	LCD_SendDat(0x01); //
    
    	LCD_SendCmd(0xbd); //Common driver output select
    	LCD_SendDat(0x00); //
    	LCD_SendCmd(0xbe); //Power control
    	LCD_SendDat(0x54); //0x58 before
    	LCD_SendCmd(0x11); //sleep out
    	__delay_cycles(800000);
    	LCD_SendCmd(0xba); //Voltage control
    	LCD_SendDat(0x2f); //
    	LCD_SendDat(0x03); //
    
    	LCD_SendCmd(0x25); //Write contrast
    	LCD_SendDat(0x60); //
    
    	LCD_SendCmd(0xb7); //Temperature gradient
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x00); //
    
    	LCD_SendCmd(0x03); //Booster voltage ON
    	__delay_cycles(800000);
    	LCD_SendCmd(0x36); //Memory access control
    	LCD_SendDat(0x48); //
    
    	LCD_SendCmd(0x2d); //Color set
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x03); //
    	LCD_SendDat(0x05); //
    	LCD_SendDat(0x07); //
    	LCD_SendDat(0x09); //
    	LCD_SendDat(0x0b); //
    	LCD_SendDat(0x0d); //
    	LCD_SendDat(0x0f); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x03); //
    	LCD_SendDat(0x05); //
    	LCD_SendDat(0x07); //
    	LCD_SendDat(0x09); //
    	LCD_SendDat(0x0b); //
    	LCD_SendDat(0x0d); //
    	LCD_SendDat(0x0f); //
    	LCD_SendDat(0x00); //
    	LCD_SendDat(0x05); //
    	LCD_SendDat(0x0b); //
    	LCD_SendDat(0x0f); //
    
    	LCD_SendCmd(0x3a); //interface pixel format
    	LCD_SendDat(0x03); // 0x02 for 8-bit 0x03 for 12bit
    	__delay_cycles(1600000);
    
    	LCD_SendCmd(0x29); //Display ON
    }
    



    Наш адрес не дом и не улица, наш адрес такой...



    Включив дисплей, мы увидим либо мусор, либо белый/черный экран. Все потому, что контроллер изменяет состояние матрицы относительно внутренней памяти, и включив его, он отобразит все, что он «помнит». Для отображения какой-либо информации (либо ее изменения) достаточно изменить память и контроллер обновит дисплей (обновляет он дисплей постоянно с определенной частотой, задаваемой в первоначальной настройке, по умолчанию частота обновления 85Hz). Например, для смены цвета пикселя нужно просто записать новое значение в память. Но для начала нужно задать адрес, куда записывать новое значение. Если в компьютере просто задается адрес ячейки памяти и записывается новое значение, то тут надо указать диапазон памяти, в который можно последовательно отправить данные.

    Например, для заливки всего экрана нужно выбрать начало записываемой области (x0, y0) и конец (x101, y80). А если нужно поменять цвет только одного пиксела, то соответственно задаем область [x, y][x+1, y+1].

    Выбрав область, мы можем теперь просто отправлять данные и они последовательно будут записываться в память (а как именно (слева на право, сверху вниз или наоборот) будет зависеть от первоначальной настройки). Например выбрав область 40х40px, нам нужно будет отправить последовательно 1600 значений (правда это не совсем так, но об этом по порядку), которые будут внесены в память и эта область будет полностью обновлена. А если продолжить отправлять значения, то обновление продолжится со следующего пиксела (в данном случае с первого).

    Команды для задания области
    LCD_SendCmd(0x2A); //задаем область по X (x0 - начальный, x1 - конечный)
    LCD_SendDat(x0);
    LCD_SendDat(x1);
    
    LCD_SendCmd(0x2B); //задаем область по Y (y0 - начальный, y1 - конечный)
    LCD_SendDat(y0+1); //у этого контроллера Y отсчитывается от 1, а не 0
    LCD_SendDat(y1+1);
    
    LCD_SendCmd(0x2C); // отправляем команду на начало записи в память и начинаем посылать данные
    



    Вам письмо! Правда на Китайском...



    Мы уже разобрались как включить дисплей и даже как выбрать область для рисования, но как цвет то отправлять? Дисплей может работать с 2 цветовыми палитрами:
    • 8bit (256 цветов)
    • 12bit (4096 цветов)

    В случае 8 битного цвета все просто — достаточно отправлять 8 бит на каждый цвет (а именно R2R1R0G2G1G0B1B0, где R2R1R0 — 3 бита красного цвета и тд. На красный и зеленый по 3 бита, а на синий 2 бита).
    А вот в случае 12 битного цвета все немого сложнее. Тут уже для каждого оттенка дается по 4 бита. Приведу картинку из даташита.

    Как видите, для отправки одного цвета используется полтора байта. Если надо изменить только 1 пиксел, то отправляется 2 байта информации, где во втором байте D3-D0 не будут использоваться. А если надо изменить 2 пиксела, то достаточно отправить 3 байта (где D3-D0 второго байта будут началом, а D7-D0 третьего байта продолжением цвета для второго пиксела ).

    Опять порция кода
    Пример функции заливки всего экрана.
    void LCD_Flush(unsigned char R, unsigned char G, unsigned char B)
    {
    	volatile int i = 4040;
    
    	volatile char B0, B1, B2;
    	B0 = ((R << 4) & 0xF0) + (G & 0x0F);
    	B1 = ((B << 4) & 0xF0) + (R & 0x0F);
    	B2 = ((G << 4) & 0xF0) + (B & 0x0F);
    
    	LCD_SendCmd(0x2A);
    	LCD_SendDat(0);
    	LCD_SendDat(100);
    
    	LCD_SendCmd(0x2B);
    	LCD_SendDat(1);
    	LCD_SendDat(80);
    
    	LCD_SendCmd(0x2C);
    
    	while (i--)
    	{
    		LCD_CD_OUT |= LCD_CD;
    		SPI = B0;
    		SPI = B1;
    		SPI = B2;
    	}
    }
    



    А где обещанные часики?



    А теперь самое сложное — нарисовать часики. Как вы могли заметить, они стилизованы под сегментный индикатор, так что для отображения часов достаточно нарисовать 2 типа сегментов (вертикальные и горизонтальные) в разных местах.
    Для начала надо определиться с дизайном. Спасибо великой программе от MS — Paint, очень уж она мне помогла с этим;).

    Вот что у меня получилось. Каждый сегмент размером 12х4px (а вертикальные соответственно наоборот — 4x12px).

    А теперь вспомним про выбор области для рисования. Можно же задать область 12х4 в нужном месте и отрисовать сегмент, не перерисовывая весь экран. Если повнимательнее взглянуть на сегмент, можно заметить, что он почти полностью заливается одним цветом, за исключением углов. Так что алгоритм рисования сегмента довольно простой: начинаем заполнение памяти с пустого цвета (к сожалению тут нет прозрачности, так что заполняем цветом фона), добавляем проверки для верхнего правого и нижнего левого угла, и последний пиксел тоже заполняем цветом фона. Точно так же и для вертикальных. А уж как нарисовать точечки я даже не буду рассказывать:).

    Набор матерных слов на непонятном языке
    Пример функции для отображения горизонтального сегмента. greenBright — константа «яркого» цвета (для активного сегмента), greenDim — константа цвета для неактивного сегмента. BG0, BG1, BG2 — константы битов для зарисовки фона.
    А если заметите __delay_cycles — это необъяснимая магия, без которой не работает (хотя скорее всего не успевает хардварный SPI отправлять данные, так как они отправляются не за один такт (но намного быстрее, в отличии если реализовать отправку своими силами)).
    void drawHorizontal(char type, unsigned char x, unsigned char y)
    {
    	volatile unsigned char i = 22, B2, B1, B0;
    	if (type)
    	{
    		B0 = greenBright;
    		B1 = 0;
    		B2 = (greenBright << 4) & 0xF0;
    	} else {
    		B0 = greenDim;
    		B1 = 0;
    		B2 = (greenDim << 4) & 0xF0;
    	}
    
    	LCD_SendCmd(0x2A);
    	LCD_SendDat(x);
    	LCD_SendDat(x+11);
    
    	LCD_SendCmd(0x2B);
    	LCD_SendDat(y+1);
    	LCD_SendDat(y+4);
    
    	LCD_SendCmd(0x2C);
    
    	__delay_cycles(4);
    
    	LCD_CD_OUT |= LCD_CD;
    	SPI = BG0;
    	SPI = (BG1 << 4) & 0xF0;
    	__delay_cycles(2);
    	SPI = B2;
    
    	while(i--)
    	{
    		if (i == 17)
    		{
    			SPI = B0;
    			__delay_cycles(2);
    			SPI = (BG0 >> 4) & 0x0F;
    			__delay_cycles(2);
    			SPI = (BG0 << 4) & 0xF0 + (BG1 << 4) & 0x0F;
    			continue;
    		}
    		if (i == 4)
    		{
    			SPI = BG0;
    			SPI = (BG1 << 4) & 0xF0;
    			__delay_cycles(2);
    			SPI = B2;
    			continue;
    		}
    		SPI = B0;
    		SPI = B1;
    		SPI = B2;
    
    	}
    
    	SPI = B0;
    	__delay_cycles(2);
    	SPI = (BG0 >> 4) & 0x0F;
    	__delay_cycles(2);
    	SPI = (BG0 << 4) & 0xF0 + (BG1 << 4) & 0x0F;
    }
    



    Теперь надо превратить цифру в набор сегментов (например для отображения 1 надо нарисовать только правые вертикальные сегменты). Я это решил довольно просто — создал массив значений сегментов для различных цифр (от 0 до 9). Подставляя в него цифру, я получаю массив со значениями 1/0, которые управляли отрисовкой сегментов. Например 1 означала, что сегмент нужно отрисовывать, а 0 — что не надо (или отрисовать его «неактивным»). А зная что и где надо рисовать, сделать функцию не составит труда.
    Простенький массивчик
    /********************************************************************************************
    * 	Array for Clock
    *  	   	   ____
    * 		 _|__1_|_
    * 		|6|    |2|
    * 		|_|____|_|
    * 		 _|__7_|_
    * 		|5|    |3|
    * 		|_|____|_|
    * 		  |__4_|
    *
    ********************************************************************************************/
    static const char HH[10][7] = {
    		{1,1,1,1,1,1,0}, // 0
    		{0,1,1,0,0,0,0}, // 1
    		{1,1,0,1,1,0,1}, // 2
    		{1,1,1,1,0,0,1}, // 3
    		{0,1,1,0,0,1,1}, // 4
    		{1,0,1,1,0,1,1}, // 5
    		{1,0,1,1,1,1,1}, // 6
    		{1,1,1,0,0,0,0}, // 7
    		{1,1,1,1,1,1,1}, // 8
    		{1,1,1,1,0,1,1}  // 9
    };
    

    Код рисования часов
    void drawClock(char hh, char mm, char dots)
    {
    	volatile char h0, h1, m0, m1;
    	h0 = hh / 10;
    	h1 = hh - (h0 * 10);
    	m0 = mm / 10;
    	m1 = mm - (m0 * 10);
    
    
    
    	drawHorizontal(HH[h0][0], 9, 25);
    	drawHorizontal(HH[h1][0], 31, 25);
    	drawHorizontal(HH[m0][0], 58, 25);
    	drawHorizontal(HH[m1][0], 80, 25);
    
    	drawVertical(HH[h0][5], 6, 29);
    	drawVertical(HH[h0][1], 20, 29);
    
    	drawVertical(HH[h1][5], 28, 29);
    	drawVertical(HH[h1][1], 42, 29);
    
    	drawVertical(HH[m0][5], 55, 29);
    	drawVertical(HH[m0][1], 69, 29);
    
    	drawVertical(HH[m1][5], 77, 29);
    	drawVertical(HH[m1][1], 91, 29);
    
    	drawHorizontal(HH[h0][6], 9, 38);
    	drawHorizontal(HH[h1][6], 31, 38);
    	drawHorizontal(HH[m0][6], 58, 38);
    	drawHorizontal(HH[m1][6], 80, 38);
    
    	drawVertical(HH[h0][4], 6, 42);
    	drawVertical(HH[h0][2], 20, 42);
    
    	drawVertical(HH[h1][4], 28, 42);
    	drawVertical(HH[h1][2], 42, 42);
    
    	drawVertical(HH[m0][4], 55, 42);
    	drawVertical(HH[m0][2], 69, 42);
    
    	drawVertical(HH[m1][4], 77, 42);
    	drawVertical(HH[m1][2], 91, 42);
    
    	drawHorizontal(HH[h0][3], 9, 51);
    	drawHorizontal(HH[h1][3], 31, 51);
    	drawHorizontal(HH[m0][3], 58, 51);
    	drawHorizontal(HH[m1][3], 80, 51);
    
    	drawDots(dots);
    }
    



    И вот мы подошли к концу статьи. Надеюсь я смог максимально подробно объяснить принцип их работы:) И на закуску небольшое видео, как они работают и мигают «точками».




    P.S.
    Возможно в этой статье присутствуют орфографические, грамматические и пунктуационные ошибки. Если вы найдете их, убедительно прошу отправить мне сообщение в личку, а не писать комментарий.
    В статье не написано про реализацию часов как таковых потому что они не доделаны:) Изначально планировалось сделать небольшой гаджет, где бы использовался дисплей, внешняя flash память и внешние часы-календарь, но так как я случайно купил не те часы, все встало:) Еще одна из причин — хотелось использовать дисплей побольше, но не смог купить подходящий, например от китайской Nokla n95 8gb. Может кто подскажет где такой купить?
    Если кому-то понадобится исходный код — обращайтесь, могу поделиться:) Если у кого есть вопросы по реализации вывода символов на экран (печать текста) — могу так же поделиться исходным кодом (я не стал о нем писать, тут вроде статья про часы:), да и на отдельный пост тоже не тянет). Так же могу поделиться библиотекой для работы с экраном от Siemens CX75 (на контроллере SSD-1286, есть даже даташит), писал для себя, но случайно спалил его.
    Поделиться публикацией

    Похожие публикации

    Комментарии 17
      0
      в кдпв присутствуют волшебные диаграммы а где код работы с spi? инициализация, обработка прерывания?
        +1
        Я специально в статье сделал упор не на выкладывание быдлокода, а на объяснение принципа работы с дисплеем. Неужели в интернете нет описания инициализации SPI (да даже на хабре есть куча статей про MSP430, где очень часто используется SPI)?
        Инициализация SPI
        	UCA0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC;  // 3-pin, 8-bit SPI master
        	UCA0CTL1 |= UCSSEL_2;                     // SMCLK
        	UCA0BR0 |= 0x01;                          // /2
        	UCA0BR1 = 0;                              //
        	UCA0MCTL = 0;                             // No modulation
        	UCA0CTL1 &= ~UCSWRST;      // **Initialize USCI state machine**
        


        Как повысить частоту до 16MHz
        	BCSCTL1 = CALBC1_16MHZ;	// Set Clock Speed
        	DCOCTL = CALDCO_16MHZ;	// to 16MHz
        


        А прерывания я даже не использовал, так как ответа я не ждал от дисплея, да и без них работает (да я знаю, что по хорошему их надо использовать).
        +6
        Если кому-то понадобится исходный код — обращайтесь, могу поделиться:)

        Сам я для MSP430 не программировал ещё, но, думаю, стоило приложить исходники сразу, а то так статья как анонс смотрится.
          0
          В целом в статье не только описаны принципы работы, но и программная реализация этой части. В самих же исходниках есть только дополнительно функции для вывода текста, а так же шрифт руск/англ букв и основных символов размером 8х14, и всякий дополнительный мусор.
          А если и выкладывать, то куда?
            0
            Это как Вам удобнее.
            Я думаю, можно прямо в статье, только, под спойлер спрятать и всё.
              0
              Насколько я знаю, у бесплатных хостингов ограниченное время хранения файлов и будет не хорошо, если кому-нибудь они понадобятся, а срок их хранения истек. Есть ли бесплатные альтернативы с максимальным сроком хранения?
                0
                Я использую Dropbox и Яндекс.Диск, пока сам не удалишь — не пропадет.
          +3
          А откуда берется собственно время?
            0
            В данный момент времени как такового нету, так как хотел использовать внешний чип часов-календаря. А мигание точек — бесконечный цикл:)
              0
              Т.е. заголовок статьи не совсем оправдан? Я надеюсь, что Вы не забросите и обновите статью, когда устройство станет действительно часами? :)
              P.S.
              Я, честно говоря, думал, что раз часы «простенькие», то время по таймеру контроллера считается.
                0
                Я скорее хотел описать работу с дисплеем, а не просто вывести Hello, World (или просто залить экран, что является не очень интересным). Если я смогу найти более подходящий дисплей (дюйма так на 3-4), то доделаю девайс и напишу еще одну статью. Там уже расскажу про работу с внешними часами-календарем, а так же flash памятью.
                Просто когда пришел msp430 мигать лампочками надоело через 2 минуты и захотелось узнать его поглубже. А как это сделать? Поставить перед собой какую-нибудь задачу. Я вот захотел сделать что-то на подобии PipBoy и пошло поехало. Когда стремишься к какой то цели, очень легко получается изучать что то новое (если конечно очень хочешь достичь этой цели). И если до получения на руки msp430 я даже представлял как это все работает, то через несколько дней я уже рисовал и писал текст на дисплее, а так же понял принцип работы микроконтроллеров (да и не только их! по сути компьютеры те же микроконтроллеры).
                0
                а зачем использовать внешний чип, там с ланчпадами же идет часовой кварц и от него можно прерываться и считать время и календарь =) еще и в спячку ложить все остальное, если экран сохраняет картинку
                  0
                  можно, но хочется же поизвращаться:)
              0
              от китайской Nokla n95 8gb. Может кто подскажет где такой купить?

              Тут не смотрели?
                0
                Смотрел:) Даже ходил туда. В 2х их магазинах, расположенных в Питере таких дисплеев нет.
                0
                Вот действительно простые часы на MSP430: www.simpleavr.com/msp430-projects/3p4w-clock Видео особенно впечатляет, где менее чем за минуту собираем полноценные часы с будильником.
                У Вас же скорее рассмотрена работа с экраном от телефона, что конечно же не умаляет Ваш труд.

                У платформы MSP430 интересный ассемблер, я только ради этого LaunchPad приобрел, чтобы попрограммировать на ассемблере :)
                  0
                  Спасибо за статью! Поделитесь библиотекой для работы с экраном от Siemens CX75 (на контроллере SSD-1286), буду ковырять. Спасибо.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое