Текст программ на языке VHDL для калибровки цифрового трёхосного MEMS акселерометра
Текст программ на языке VHDL для калибровки цифрового трёхосного MEMS акселерометра
Аннотация к программе
акселерометр калибровка цифровой программа
В документе представлены программы, необходимые для правильной работы устройства калибровки цифрового акселерометра и реализующие обмен данными по протоколу SPI между акселерометром и ПЛИС, а так же RS-232 для передачи данных с макета на ПЭВМ.
Программа позволяет выполнять инициализацию MEMS-акселерометра, принимать от него байты данных соответствующие текущему угловому состоянию датчика и его ускорению.
Программа разработана в среде Quartus II Software Version 9.0. Для ее функционирования требуется наличие на компьютере операционной системы Windows XP/Vista/7.
1. SPI-Master
-объявление пакета(собственной библиотеки)
package spi_pack isspi_states is (sleep, init, rw, iready, status); --iwait --ЦКАbyte is natural range 0 to 255;
--регистр управления режимами работы по мощности и частотой вывода данных(дискретизации)
Constant BW_RATE: byte := 44;
-регистр управления спящим режимом и частотой показаний в спящем режиме
Constant POWER_CTRL: byte := 45;
-регистр управления прерыванием
Constant INT_ENABLE: byte := 46;
-регистр управления логическим уровнем прерывания, выравниванием бит данных и разрядностью
Constant DATA_FORMAT: byte := 49;
-готовность передачи Status_REG: byte := 48;
-ускорение акселерометра по трем осям чувствительности
Constant DATA_X0: byte := 50;
Constant BW_RATE_WORD: byte := 10;--14;--12
--нормальный режим работы, режим измерения
Constant POWER_CTRL_WORD: byte := 8;
--прерывание разрешеноINT_ENABLE_WORD: byte := 128;
--диапазон измеряемых ускорений - ±4g, выравнивание бит - по левому краю, 11 разрядов
Constant DATA_FORMAT_WORD: byte := 13;
--кол-во инициализируемых регистров
Constant all_init_regs: byte := 4;
-кол-во читаемых регистров(по 2 байта на каждую ось чувствительности)
Constant all_read_regs: byte := 6;gyro_regs is array (0 to all_init_regs-1) of byte;init_addreses: gyro_regs := (BW_RATE, POWER_CTRL, INT_ENABLE,DATA_FORMAT);ctrl_data: gyro_regs := (BW_RATE_WORD, POWER_CTRL_WORD, INT_ENABLE_WORD, DATA_FORMAT_WORD);
--количество тактовых импульсов(частота дискретизации)1МГЦ/100Гц
Constant Discrete: natural range 0 to 16_383 := 10_000;--1_000_000/625 ;--10_000 -- 2500spi_pack;
-объявление библиотекieee;ieee.std_logic_1164.all;ieee.std_logic_arith.all;ieee.std_logic_unsigned.all;work.spi_pack.all;spi_core is
(
--сигнал разрешения передачи данных (передача по низкому логическому уровню)
cs: out std_logic;
-тактовый сигнал: out std_logic;
--выходной сигнал SPI для подачи на вход акселерометра
sdi: out std_logic;
-входящий высокочастотный сигнал
-входной сигнал SPI для чтения данных с выхода SDO акселерометра
sdo: in std_logic;
-биты данных для одной оси чувчтвительности
data_out: out std_logic_vector(15 downto 0);
-выход передачи UART: out std_logic;
-вход приема UART: in std_logic
);spi_core;Behavior of spi_core is
--делитель
Component divider is
-настроечная константа
generic (N : natural := 8);
(
-тактовый сигнал: in std_logic;
-сигнал сброса: in std_logic;
-сигналы установки и чтения по разным фронтам
clk_out: out std_LOGIC;_scl: out std_LOGIC
);Component;
-передатчикtx_uart is
(
-скорость передачи
-частота дискретизации
Fd: natural := 100;
-кол-во передаваемых байт по умолчанию
n_bytes: natural := 6
);
port
(
-тактовый высокочастотный сигнал
clock : in std_logic;
-сигнал сброса : in std_logic;
-массив бит входных данных длиной 8*кол-во байт
data_tx: in std_logic_vector(8*n_bytes - 1 downto 0);
-выход UART: out std_LOGIC
);Component;gyro_reads is array (0 to all_read_regs-1) of std_logic_vector(7 downto 0);new_data, new_data_temp, init_ready, rst: std_logic;clk, clk_for_scl, scl_ena: std_logic;wd: std_logic;n_bit: natural range 0 to 8*(all_read_regs + 1) -1;num_init: natural range 0 to all_init_regs;num_read: natural range 0 to all_read_regs;D_out: gyro_reads;ready: std_logic;data_tx: std_logic_vector(8*all_read_regs - 1 downto 0);cnt: std_logic;state, next_state: spi_states;_freq: divider generic map (N => 24) port map (clock, '1', clk, clk_for_scl);(state, wd, init_ready, n_bit, new_data, num_read)(state) issleep => if (init_ready = '0') then next_state <= init;(wd = '1') then next_state <= status;(new_data = '1') then next_state <= rw;next_state <= sleep;if;init => if (n_bit = 15)next_state <= sleep;next_state <= init;if;status => if (n_bit = 15)next_state <= sleep;next_state <= status;if;rw => if (n_bit = (8*(all_read_regs + 1) -1))next_state <= iready;next_state <= rw;if;iready => next_state <= sleep;others => null;case;process;(clk, cnt)(cnt = '0') then n_bit <= 0;(clk'event and clk = '0') then_bit <= n_bit + 1;if;process;(clk)cycle: natural range 0 to Discrete;(clk'event and clk = '0') then<= next_state;cycle = 0wd <= '1';wd <= '0';if;cycle = Discrete - 1cycle := 0; cycle := cycle + 1;if;if;process; (clock, state, n_bit, num_init, num_read)cycle: natural range 0 to Discrete;data: std_logic_vector(15 downto 0); (clock'event and clock = '1') then(state) issleep => sdi <= '0';<= '1';_ena <= '0';<= '0'; init => cs <= '0';_ena <= '1'; := "00" & conv_std_logic_vector(init_addreses(num_init), 6) & conv_std_logic_vector(ctrl_data(num_init), 8);<= data(15 - n_bit);<= '1';status => cs <= '0';_ena <= '1';:= "10" & conv_std_logic_vector(Status_REG, 6) & "11111111";<= data(15 - n_bit);<= '1';rw => cs <= '0';_ena <= '1';:= "11" & conv_std_logic_vector(DATA_X0, 6) & "11111111";(n_bit < 16) then<= data(15 - n_bit);<= '1';if;<= '1';iready => cs <= '1';_ena <= '0';<= '0';<= '0';others => null;case;if;process; (clk, state, n_bit, new_data)data: gyro_reads;(clk'event and clk = '0') then(state) issleep => num_read <= 0;init => if (n_bit = 15) then(num_init = all_init_regs - 1)init_ready <= '1';init_ready <= '0';_init <= num_init + 1;if;if;status => if (n_bit = 8)new_data <= sdo;if;rw => if (n_bit > 7)data(num_read)(7 - (n_bit rem 8)) := sdo;(n_bit rem 8 = 7)num_read <= num_read + 1;if;if;iready => data_out <= data(1) & data(0);_data <= '0';_tx <= data(1) & data(0) & data(3) & data(2) & data(5) & data(4);others => null;case;if; process;<= '1' when scl_ena = '0' else clk_for_scl;_UART_Tx: tx_uart generic map (Rapid => 460_800,=> 100,_bytes => all_read_regs)map
(=> clock,=> not rx,_tx => data_tx,=> tx
);
end Behavior;
. Параметрический делитель частоты с асинхронным сбросом
library IEEE;IEEE.std_logic_1164.all;IEEE.std_logic_arith.all;IEEE.std_logic_unsigned.all;divider is(N : natural);
( : in std_logic;: in std_logic;
);divider;behavior of divider is(clk, reset)cnt: natural := 0;(reset = '0') then:= 0; clk_out <= '0'; clk_scl <= '0'; (clk'event and clk = '1') thencnt is0 => clk_out <= '0'; clk_scl <= '1';N/2 => clk_out <= '1'; clk_scl <= '0';others => null;case;cnt = N -1 then cnt := 0;cnt := cnt + 1;if;if;process;behavior;
1.3 Передатчик UART
package UART_settings isFreq: natural := 24_000_000;package;IEEE;IEEE.std_logic_1164.all;IEEE.std_logic_arith.all;IEEE.std_logic_unsigned.all;work.UART_settings.all;tx_uart is
(: natural := 115_200;: natural := 100;_bytes: natural := 6
-parity: parity_bit := no
);
(: in std_logic;_tx: in std_logic_vector(8*n_bytes - 1 downto 0);: out std_LOGIC
);tx_uart;Behavior of tx_uart isdivider is(N : natural);
( : in std_logic;: in std_logic;_out: out std_LOGIC
);component;Discr: natural := Rapid/Fd;UART_states is (sleep, start, dtx, stop);state, next_state: UART_states := sleep;clk: std_logic;counter: natural range 0 to 15;cnt: std_logic;period: std_logic;sent: std_logic;num: natural range 0 to n_bytes;: divider generic map (N => Freq/Rapid) port map (clock, '1', clk);(clock, state, num)data: std_logic_vector(8*n_bytes - 1 downto 0);(clock'event and clock = '1') then(state) is(sleep) => tx <= '1';<= '0';<= '0';start=> tx <= '0';<= '0';<= '0';(num = 0)data := data_tx;if;stop => tx <= '1';<= '0';<= '1';dtx => cnt <= '1';<= '0';counter /=8 then <= data(8*(n_bytes - num) - 8 + counter);tx <= data(8*(n_bytes - num) - 1) xor data(8*(n_bytes - num) - 2) xor(8*(n_bytes - num) - 3) xor data(8*(n_bytes - num) - 4) xor(8*(n_bytes - num) - 5) xor data(8*(n_bytes - num) - 6) xor(8*(n_bytes - num) - 7) xor data(8*(n_bytes - num) - 8) xor '1';if;others => null;case;if;process;(state, num, counter, period)(state) is(sleep) => if period = '1' then next_state <= start;next_state <= sleep;if;start=> next_state <= dtx;stop => if (num = n_bytes) then_state <= sleep;_state <= start;if;dtx =>if (counter) = 7 then --no
-if (counter) = 8 then -- even or odd_state <= stop;next_state <= dtx;if;others => null;case;process;(clk, cnt)(cnt = '0') then counter <= 0;(clk'event and clk = '0') then<= counter + 1;if;process;(sent, period) (period = '1') then num <= 0;(sent'event and sent = '1') thennum = n_bytes then<= 0;<= num + 1;if;if;process; (clk)cycle: natural range 0 to Discr;(clk'event and clk = '0') then<= next_state;cycle = 0period <= '1';period <= '0';if;cycle = Discr - 1cycle := 0; cycle := cycle + 1;if;if;process; Behavior;