Портирование MIPSfpga на другие платы и интеграция периферии в систему. Часть 3

  • Tutorial
В первой части я описал на примере cmoda7 как портировать MIPSfpga (Портирование MIPSfpga на другие платы и интеграция периферии в систему. Часть 1) на FPGA платы отличные от уже портированых среди которых такие популярные как: basys3, nexys4, nexys4_ddr фирмы Xilinx, а так же de0, de0_cv, de0_nano, de1, DE1, de10_lite, de2_115, DE2-115 фирмы Altera(Intel), во второй части как интегрировать клавиатуру Pmod KYPD (Портирование MIPSfpga на другие платы и интеграция периферии в систему. Часть 2).

В этой части добавим к MIPSfpga-plus встроенный АЦП, и популярный LCD от Nokia 5100.
С предыдущих частей можно сделать вывод, что интеграция периферии в MIPSFPGA состоит из пять основных этапов:
  • Добавление модуля интерфейса общения с периферией (i2c, spi, и т.д.).
  • Соединение входных/выходных портов модуля с шиной AHB-Lite.
  • Присваивание адресов сигналов подключаемого устройства.
  • Добавление констрейнов на физические контакты платы.
  • Написание программы для MIPS процессора.


Подключение встроенного в cmoda7 АЦП



Как я уже говорил плата cmodA7 имеет встроенный АЦП, pin 15 и 16 используются в качестве аналоговых входов модуля FPGA. Диапазон работы встроенного АЦП от 0-1V, поэтому используется внешняя схема для увеличения входного напряжения до 3.3V.


Эта схема позволяет модулю XACD точно измерить любое напряжение от 0 В и 3,3 В (по отношению к GND). Чтобы работать с АЦП в Vivado существует блок IP (интеллектуальной собственности) Xilinx, с помощью которого можно будет просто его интегрировать в нашу систему MIPSfpga.

Добавление модуля


Откроем наш проект созданый в предыдущих частях (Часть 1 , Часть 2). Для начала нам нужно создать модуль взаимодействия IP с ситемой. В Vivado выполним Add source -> Add or create design sources -> Create file -> (назовем xadc) -> Finish -> Ok -> Yes. В разделе Source откроем файл.
Далее нам нужно добавить IP.
Во вкладке Project manager выбираем IP Catalog. Перейдем в папку FPGA Features and Design -> XADC -> XADC Wizard и откроем.
Следующим шагом будет настройка блока XADC. Во вкладке Basic установим значения как на изображении:

Если кратко то в этой вкладке мы установили частоту дискретизации, режим работы АЦП, и каналов.
Перейдем во вкладку ADC Setup:


Так как мы не будем использовать все сигналы предупреждений:


Во вкладке Basic мы выбрали режим Single channel(так мы используем один канал VAux4):


Жмем Ok -> Generate. После того как мы создали IP нужно его добавить в модуль xadc:
`timescale 1ns / 1ps

module xadc(    input i_clk,
                input i_rst_n,
                input i_xa_p,
                input i_xa_n,
                output reg [15:0] xadc_data
            );

wire [15:0] do_out;

xadc_wiz_0 wiz
             (
              .daddr_in(8'h14),    // Address bus for the dynamic reconfiguration port
              .dclk_in(i_clk),     // Clock input for the dynamic reconfiguration port
              .den_in(1'b1),       // Enable Signal for the dynamic reconfiguration port
              .di_in(16'b0),       // Input data bus for the dynamic reconfiguration port
              .dwe_in(1'b0),       // Write Enable for the dynamic reconfiguration port
              .vauxp4(i_xa_p),     // Auxiliary channel 4
              .vauxn4(i_xa_n),
              .busy_out(),         // ADC Busy signal
              .channel_out(),      // Channel Selection Outputs
              .do_out(do_out),     // Output data bus for dynamic reconfiguration port
              .drdy_out(),         // Data ready signal for the dynamic reconfiguration port
              .eoc_out(),          // End of Conversion Signal
              .eos_out(),          // End of Sequence Signal
              .alarm_out(),        // OR'ed output of all the Alarms    
              .vp_in(1'b0),        // Dedicated Analog Input Pair
              .vn_in(1'b0)
             );

always @(posedge i_clk, negedge i_rst_n)
if (!i_rst_n)
    xadc_data <= 16'b0;
else
    xadc_data <= do_out;

endmodule


Соединение входных/выходных портов модуля с шиной AHB-Lite


Пройдемся кратко по иерархии системы MIPSfpga и добавим нужные соединения:
В «mfp_system» добавим входные сигналы с модуля оболочки:
    `ifdef MFP_XADC
     input  I_XA_P,
     input  I_XA_N,
    `endif

сигнал типа wire для соединения экземпляров «xadc» и «mfp_ahb_lite_matrix_with_loader»:
    `ifdef MFP_XADC
     wire [15:0] XADC_DATA;
    `endif

    `ifdef MFP_XADC
     .XADC_DATA        (    XADC_DATA       ),
    `endif

И подключим сам екземпляр модуля xadc:
  `ifdef MFP_XADC
    xadc xadc
    (    
        .i_clk      (   SI_ClkIn  ),
        .i_rst_n    ( ~SI_Reset     ),
        .i_xa_p     (   I_XA_P      ),
        .i_xa_n     (   I_XA_N      ),
        .xadc_data  (   XADC_DATA   )
     );
    `endif

В «mfp_ahb_lite_matrix_with_loader»:
    `ifdef MFP_XADC
        input [15:0]     XADC_DATA,
    `endif

    `ifdef MFP_XADC
     .XADC_DATA        (    XADC_DATA       ),
    `endif

В «mfp_ahb_lite_matrix»:
    `ifdef MFP_XADC
     input [15:0]  XADC_DATA,
    `endif

   `ifdef MFP_XADC
    .XADC_DATA        (    XADC_DATA       ),
   `endif

В «mfp_ahb_gpio_slave» добавим выходной порт:
    `ifdef MFP_XADC
     input [15:0] XADC_DATA,
    `endif

и во второй always блок добавим на вход мультиплексора определяющего периферию:
    `ifdef MFP_XADC
     `MFP_XADC_IONUM  : HRDATA <= { 16'b0, XADC_DATA };
    `endif

Вернемся по иерархии в топ модуль оболочку, и добавим сигналы соединения с физическими контактами на плате:
    input         i_xa_p,
    input         i_xa_n,

и добавим в экземпляр «mfp_system»:
   `ifdef MFP_XADC
   .I_XA_P           (   i_xa_p         ),
   .I_XA_N           (   i_xa_n         ),
   `endif

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


Присваивание адреса выполняется конфигурационном файле «mfp_ahb_litematrix_config.vh»:
Для начала добавим строчку комментируя//расскоментируя которую можно включать исключать написаные в проекте нами строки конкретной периферии определённой в данном случае `ifdef MFP_XADC… `endif:
`define MFP_XADC

определим адрес:
`ifdef MFP_XADC
`define MFP_XADC_ADDR               32'h1f80001C
`endif

А так же, константу определяющую адрес:
`ifdef MFP_XADC            
`define MFP_XADC_IONUM              4'h7
`endif

Добавление констрейнов на физические контакты платы


В файл *.xdc теперь нужно добавить созданные нами сигналы. Во встроенном АЦП платы cmodA7 у нас эти контакты имеют имя ADx_P — G2, и ADx_N — G3, добавим их в файл:
## Analog XADC Pins
set_property -dict {PACKAGE_PIN G2 IOSTANDARD LVCMOS33} [get_ports i_xa_n]
set_property -dict {PACKAGE_PIN G3 IOSTANDARD LVCMOS33} [get_ports i_xa_p]


Написание программы для MIPS процессора


Последним этапом является написание программы для процессора который будет взаимодействовать с АЦП.
Хочу подметить что основной целью статьи является демонстрация возможностей такого проекта как MIPSfpga, потому в коде всего пару строк. В какой то степени это и является точка отправления как для программистов которые решили выучить цифровой дизайн, так и дизайнеров которые решили больше углубится в программирование процессоров.
Гибкость состоит в том, что можно написать простейший модуль на Verilog(VHDL), и сложную програму на Си например реализовать SPI большим кодом, и наоборот.

Процессор MIPSfpga программируют с использованием инструментов разработки Codescape компании Imagination. Установите Codescape SDK и OpenOCD. Codescape поддерживает программирование как на языке C, так и на языке ассемблера.
Для загрузки кода в систему нужно перейти в папку скачаного mipsfpga plus ->github->mipsfpga-plus->programs->01_light_sensor откроем «mfp_memory_mapped_registers.h»
#define MFP_XADC_ADDR           0xBF80001С
и
#define MFP_XADC                (* (volatile unsigned *) MFP_XADC_ADDR          )

далее откроем main.c и напишем пару строк:
#include "mfp_memory_mapped_registers.h"

void delay();

int main ()
{
    int n = 0;

    for (;;)
    {
        MFP_7_SEGMENT_HEX = MFP_XADC >> 8 ;
		delay();
    }

    return 0;
}

void delay() {
  volatile unsigned int j;

  for (j = 0; j < (1000000); j++) ;	// delay 
}

Генерируем motorola_s_record файл:
08_generate_motorola_s_record_file

Проверяем к какому СОМ порту подключен USB UART преобразователь:
11_check_which_com_port_is_used

Изменяем файл 12_upload_to_the_board_using_uart:
set a=7 
mode com%a% baud=115200 parity=n data=8 stop=1 to=off xon=off odsr=off octs=off dtr=off rts=off idsr=off type program.rec >\.\COM%a%

где а – номер СОМ порта, к которому подключен USB UART преобразователь.
И загружаем программу:
12_upload_to_the_board_using_uart

Схема подключения:

Таким образом, с АЦП в процессор поступает 16 битное число соответствующее напряжению поступающему на аналоговый вход на плате с делителя состоящего с резистора и фоторезистора, после чего процессор сдвигает данные на 8 бит в лево и выводит на семисегментный индикатор. Как видите все банально просто. Теперь можно дописывать код под наши потребности.


Интеграция LCD дисплея от Nokia 5100


В сети такой LCD дисплей среди ардуинщиков пользуется большим спросом, можно сказать они дали ему шанс на вторую жизнь применяя его в различных проектах. Поэтому и было принято решение попробовать его подключить к MIPS процессору в качестве практики.
Следующие действия я буду описывать кратко и по существу так, как все шаги подробно описаны выше.

Управление дисплеем осуществляется по интерфейсу SPI, дисплей является ведомым устройством. Однако, вместо обычных четырех линий управления здесь лишь три. Это линии тактирования CLK, выбора кристалла SCE и входных данных MOSI. Линия выхода MISO отсутствует. Это приводит к необходимости применять специальные методы управления, подробнее об этом далее. В Nokia 5110 присутствует также дополнительная линия управления Информация/Команда – D/C̅. Каждый байт, передаваемый в дисплей, может быть интерпретирован как команда или информационный байт, в зависимости от уровня на линии D/C̅.

Схема подключения:

Pin Обозначение на дисплее Обозначение выходов в XDC файле Маркировка контакта на
FPGA
Назначение
34 BL o_sbl W3 Подсветка
33 Clk o_sck V2 Сигнал синхронизации
32 Din o_sdo W2 Передача данных
30 DC o_sdc T2 Сигнал комманда/данные
29 CE o_sce T1 Сигнал разрешения передачи данных
28 RST o_rst R2 Сигнал сброса
VCC Vcc - - Питание
GND Gnd - - Земля


Добавление модуля интерфейса общения с периферией


Так как обратной связи с дисплеем не будет, можно написать модуль только на отправку данных. Даташит на дисплей Nokia 5100 LCD Display.
Напишем модуль для взаимодействия дисплея с MIPSfpga-plus и добавим его в проект.
/*
 * SPI interface for MIPSfpga
 */

module mfp_lcd_spi(
           input                                    clk,
           input                                    i_rst_n,
           input [7 : 0]                            value,
           input [2 : 0]                            ctrl,
           input                                    send,
           
           output    reg                            sdo,
           output                                   sck,
           output    reg                            ce,
           
           output    reg                            sdc,
           output    reg                            sbl,
           output    reg                            o_rst_n
           );

parameter DIV_WIDTH = 16;   // Width counter


reg [DIV_WIDTH - 1:0] counter;
reg [7:0]  data_r;
reg [3:0] bit_count_r;


// register for control signal
always @(posedge clk, negedge i_rst_n)
   if (!i_rst_n) begin

	   sdc     <= 1'b0;
       sbl     <= 1'b0;
	   o_rst_n <= 1'b0;

   end else begin

       sdc     <= ctrl[0];
       sbl     <= ctrl[1];
	   o_rst_n <= ctrl[2];

   end
//   
 

assign sck = (counter[DIV_WIDTH - 1]);


// counter for low frequency spi out
always @(posedge clk, negedge i_rst_n)
   if (!i_rst_n ) begin
	    counter <= {DIV_WIDTH{1'b0}};
   end else if (!ce)
	    counter <= counter + 1'b1;
   else 
	    counter <= {DIV_WIDTH{1'b0}};


// shift register for sending data
always @(posedge clk, negedge i_rst_n)
	if (!i_rst_n) begin

		data_r <= 8'b0;
		sdo <= 1'b0;
		bit_count_r <= 4'b1001;

	end else if (bit_count_r != 4'b1001 && counter == 0) begin
		
		sdo <= data_r[7];
		data_r <= data_r << 1;
		bit_count_r <= bit_count_r + 1'b1;


	end else if (send && ce) begin
	
		data_r <= value; 
		bit_count_r <= 4'b0000;
	
	end
//

//control register for allow data transfer
always @(posedge clk, negedge i_rst_n)
	if (!i_rst_n) begin
		ce <= 1'b1;
	end else if (!send && bit_count_r == 4'b1001)
		ce <= 1'b1;
	else 
		ce <= 1'b0;
//		
		
endmodule

Временная диаграмма модуля SPI:

Соединение входных/выходных портов модуля с шиной AHB-Lite



Добавим в «mfp_system»:
    `ifdef MFP_LCD_5100       
     output                                  IO_CE,
     output                                  SDO,
     output                                  SCK,
     output                                  SDC,
     output                                  SBL,
     output                                  RST,
    `endif

     `ifdef MFP_LCD_5100
      wire [`MFP_LCD_5100_WIDTH      - 1:0] IO_LCD_5100;
      wire [`MFP_SEND_WIDTH          - 1:0] IO_SEND;
      wire [`MFP_CTRL_WIDTH          - 1:0] IO_CTRL;
     `endif

     `ifdef MFP_LCD_5100
     .IO_LCD_5100      (   IO_LCD_5100      ),
     .IO_SEND          (   IO_SEND          ),
     .IO_CE            (   IO_CE            ),
     .IO_CTRL          (   IO_CTRL          ),
     `endif

В «mfp_ahb_lite_matrix_with_loader»:
     `ifdef MFP_LCD_5100
      output [`MFP_LCD_5100_WIDTH      - 1:0] IO_LCD_5100,
      input  [`MFP_CE_WIDTH            - 1:0] IO_CE,
      output [`MFP_SEND_WIDTH          - 1:0] IO_SEND,
      output [`MFP_CTRL_WIDTH          - 1:0] IO_CTRL,
     `endif

      `ifdef MFP_LCD_5100
      .IO_LCD_5100      ( IO_LCD_5100     ),
      .IO_CE            ( IO_CE           ),
      .IO_SEND          ( IO_SEND         ),
      .IO_CTRL          ( IO_CTRL         ),
      `endif 

В «mfp_ahb_lite_matrix»:
      `ifdef MFP_LCD_5100
       output [`MFP_LCD_5100_WIDTH      - 1:0] IO_LCD_5100,
       input  [`MFP_CE_WIDTH            - 1:0] IO_CE,
       output [`MFP_SEND_WIDTH          - 1:0] IO_SEND,
       output [`MFP_CTRL_WIDTH          - 1:0] IO_CTRL,
      `endif     

      `ifdef MFP_LCD_5100 
      .IO_LCD_5100      ( IO_LCD_5100     ),
      .IO_CE            ( IO_CE           ),
      .IO_SEND          ( IO_SEND         ),
      .IO_CTRL          ( IO_CTRL         ),
      `endif

В «mfp_ahb_gpio_slave» добавим такие строки:
      `ifdef MFP_LCD_5100
       output reg [`MFP_LCD_5100_WIDTH      - 1:0] IO_LCD_5100,
       input      [`MFP_CE_WIDTH            - 1:0] IO_CE,
       output reg [`MFP_SEND_WIDTH          - 1:0] IO_SEND,
       output reg [`MFP_CTRL_WIDTH          - 1:0] IO_CTRL,
      `endif

      `ifdef MFP_LCD_5100 
       IO_LCD_5100     <= `MFP_LCD_5100_WIDTH'b0;
       IO_CTRL         <= `MFP_CTRL_WIDTH'b0;
       IO_SEND         <= `MFP_SEND_WIDTH'b0;
      `endif

      `ifdef MFP_LCD_5100
      
      `MFP_LCD_5100_IONUM      : IO_LCD_5100     <= HWDATA [`MFP_LCD_5100_WIDTH      - 1:0];
      `MFP_CTRL_IONUM          : IO_CTRL         <= HWDATA [`MFP_CTRL_WIDTH          - 1:0];
      `MFP_SEND_IONUM          : IO_SEND         <= HWDATA [`MFP_SEND_WIDTH          - 1:0];  
      `endif

`ifdef MFP_LCD_5100
`MFP_LCD_5100_IONUM: HRDATA <= { { 32 - `MFP_LCD_5100_WIDTH{ 1'b0 } } ,IO_LCD_5100         };
`MFP_CTRL_IONUM: HRDATA     <= { { 32 - `MFP_CTRL_WIDTH    { 1'b0  } } ,IO_CTRL};
`MFP_SEND_IONUM: HRDATA     <= { { 32 - `MFP_SEND_WIDTH    { 1'b0 } } ,IO_SEND};
`MFP_CE_IONUM: HRDATA       <= { { 32 - `MFP_CE_WIDTH      { 1'b0 } } ,IO_CE};
`endif

В топ модуль оболочку добавим выходные порты на плату:
    `ifdef MFP_LCD_5100
     output o_rst, 
            o_ce,
            o_sdc,
            o_sdo,
            o_sck,
            o_sbl,
    `endif

        `ifdef MFP_LCD_5100
        .IO_CE            (    o_ce          ),
        .SDO              (    o_sdo         ),
        .SCK              (    o_sck         ),
        .SDC              (    o_sdc         ),
        .SBL              (    o_sbl         ),
        .RST              (    o_rst         ),
        `endif

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


В файл «mfp_ahb_lite_matrix_config.vh» добавим адреса и определения:
`define MFP_LCD_5100

`ifdef MFP_LCD_5100
`define MFP_LCD_5100_WIDTH          9
`define MFP_SEND_WIDTH              1
`define MFP_CE_WIDTH                1
`define MFP_CTRL_WIDTH              3
`endif

`ifdef MFP_LCD_5100
`define MFP_LCD_5100_ADDR           32'h1f800020
`define MFP_SEND_ADDR               32'h1f800024
`define MFP_CE_ADDR                 32'h1f800028
`define MFP_CTRL_ADDR               32'h1f80002C
`endif

`ifdef MFP_LCD_5100
`define MFP_LCD_5100_IONUM          4'h8
`define MFP_SEND_IONUM              4'h9
`define MFP_CE_IONUM                5'hA
`define MFP_CTRL_IONUM              5'hB        
`endif


Добавление констрейнов на физические контакты платы


Добавим выходы для дисплея в XDC файл:
### GPIO Pins 33 - 40 LCD
set_property -dict {PACKAGE_PIN W3 IOSTANDARD LVCMOS33} [get_ports o_sbl]
set_property -dict {PACKAGE_PIN V2 IOSTANDARD LVCMOS33} [get_ports o_sck]
set_property -dict {PACKAGE_PIN W2 IOSTANDARD LVCMOS33} [get_ports o_sdo]
set_property -dict {PACKAGE_PIN T2 IOSTANDARD LVCMOS33} [get_ports o_sdc]
set_property -dict {PACKAGE_PIN T1 IOSTANDARD LVCMOS33} [get_ports o_ce]
set_property -dict {PACKAGE_PIN R2 IOSTANDARD LVCMOS33} [get_ports o_rst]


Написание программы для MIPS процессора


В «mfp_memory_mapped_registers.h»:
#define MFP_LCD_5100_ADDR  		0xBF800020
#define MFP_SEND_ADDR   		0xBF800024
#define MFP_CE_ADDR      		0xBF800028
#define MFP_CTRL_ADDR    		0xBF80002C

#define value                   (* (volatile unsigned *) MFP_LCD_5100_ADDR      )
#define ctrl                    (* (volatile unsigned *) MFP_CTRL_ADDR          )
#define send                    (* (volatile unsigned *) MFP_SEND_ADDR          )
#define ce                      (* (volatile unsigned *) MFP_CE_ADDR            )

Напишем программу в main.c:
main.c
#include "mfp_memory_mapped_registers.h"
#include <stdlib.h>

void delay(int delay);  		// задержка
void waitTillLCDDone(); 		// ждём пока закончится передача 
void init();				// инициализация дисплея
void start_image();			// загрузка картинки
void disp_picture();			//обновление картинки после загрузки
void gotoXY(int x, int y);              // переход на нужные координаты
void send_byte(int command, int data);	// отравка одного байта
void clear_disp();			// очистка дисплея

int main ()
{	
	init ();
	start_image();
	delay(1000);
}

void init(){
unsigned int lcd_cmd[7] = {0x21, 0x13, 0x04, 0xC0, 0x20, 0x0C, 0x08};

unsigned int i;
  
  for (i=0; i<7; i++) {
	send_byte(0x06, lcd_cmd[i]);
  }
}

void start_image (){
unsigned int screen[504] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x07, 0x03, 0x83, 0x81, 0xC1, 0xC1, 0xE1, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC1, 0xC1, 0xC1, 0x83, 0x83, 0x07, 0x07, 0x0F, 0x1F, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x03, 0x01, 0x00, 0x00, 0xE0, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF0, 0xC0, 0x00, 0x00, 0x01, 0x07, 0x3F, 0xF3, 0xC3, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF0, 0xC0, 0x80, 0x00, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x3F, 0x1F, 0x1F, 0x0F, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
};
  
  unsigned int i;
	gotoXY(0, 0);

  for (i=0; i<504; i++) {	
	send_byte(0x7, screen[i]);
  }
  
  disp_picture();

  for (i=0; i < 4; i++){
	  send_byte(0x06, 0x0D);
	  delay(1000);
	  send_byte(0x06, 0x0C);
	  delay(1000);
  }
}

void send_byte(int command, int data){

	ctrl = command;
	value = data;
	send = 1;
	send = 0;
	waitTillLCDDone();
	waitTillLCDDone();

}

void waitTillLCDDone() {
  do {
  
  } while (!ce);
  }
  

void disp_picture(){
	send_byte(0x06, 0x0C);
	}

void clear_disp(){
	send_byte(0x06, 0x08);
}
	
void gotoXY(int x, int y)
{
  send_byte(0x6, 0x80 | x);  // Column.
  send_byte(0x6, 0x40 | y);  // Row.  ?

}

void delay(int delay) 
{
  volatile unsigned int j;
  delay = delay * 5000;
  for (j = 0; j < (delay); j++) ;	// delay 
}
  


Загружаем и имеем простую заставку Imagination Technologies, дальше только фантазия.


Выражаю большую благодарность:
— Юрию Панчулу YuriPanchul за предоставление платы cmodA7.
— Евгению Короткому — доценту кафедры конструирования электронно-вычислительной аппаратуры факультета электроники, за предоставленную периферию и возможность посещать такое место как открытая лаборатория электроники Lampa.
Поделиться публикацией
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 1
  • –1
    Диапазон работы встроенного АЦП от 0-1V, поэтому используется внешняя схема для увеличения входного напряжения до 3.3V.
    Объясните, пожалуйста, каким образом приведенная Вами
    схема
    image
    преобразует напряжение в диапазоне 0...3.3V в диапазон 0...1V?

    UPD Извините, понял: у Вас схема нарисована так, что сигнал от входа к выходу идет не слева направо, как всем привычно, а наоборот.

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

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