Цитата(Jenya7 @ Jul 2 2017, 11:31)

Мне нужно сделать драйвер для 3-х двигателей. Двигатели обычные DC Motors 24V. Двигатели имеют энкодеры для отслеживания позиции.
Хотелось чтоб энкодеры были апаратные. Обычно это делается на таймерах.
Вот задумался какой контроллер выбрать. PWM+Encoders требуют таймера. К тому же на мои нужды нужно еще 3 таймера.
У ST вроде нет контролеров заточенных под motion. У TI есть но что то не хочется связываться с TI. К тому же 3 двигателя. Есть контроллеры под такую задачу?
Основная проблема - аппаратно обработать 3 энкодера. На атмеловских AVRках я пользовался внешними интераптами но это, как мне кажется, не очень хороший способ.
так не проще сделать это на плис
программируемый PWM
Код
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity pwm_prog is
generic(
N : integer := 8); -- number of bit of PWM counter
port (
i_clk : in std_logic;
i_rstb : in std_logic;
i_sync_reset : in std_logic;
i_pwm_module : in std_logic_vector(N-1 downto 0); -- PWM Freq = clock freq/ (i_pwm_module+1); max value = 2^N-1
i_pwm_width : in std_logic_vector(N-1 downto 0); -- PWM width = (others=>0)=> OFF; i_pwm_module => MAX ON
o_pwm : out std_logic);
end pwm_prog;
architecture rtl of pwm_prog is
signal r_max_count : unsigned(N-1 downto 0);
signal r_pwm_counter : unsigned(N-1 downto 0);
signal r_pwm_width : unsigned(N-1 downto 0);
signal w_tc_pwm_counter : std_logic;
begin
w_tc_pwm_counter <= '0' when(r_pwm_counter<r_max_count) else '1'; -- use to strobe new word
--------------------------------------------------------------------
p_state_out : process(i_clk,i_rstb)
begin
if(i_rstb='0') then
r_max_count <= (others=>'0');
r_pwm_width <= (others=>'0');
r_pwm_counter <= (others=>'0');
o_pwm <= '0';
elsif(rising_edge(i_clk)) then
r_max_count <= unsigned(i_pwm_module);
if(i_sync_reset='1') then
r_pwm_width <= unsigned(i_pwm_width);
r_pwm_counter <= to_unsigned(0,N);
o_pwm <= '0';
else
if(r_pwm_counter=0) and (r_pwm_width/=r_max_count) then
o_pwm <= '0';
elsif(r_pwm_counter<=r_pwm_width) then
o_pwm <= '1';
else
o_pwm <= '0';
end if;
if(w_tc_pwm_counter='1') then
r_pwm_width <= unsigned(i_pwm_width);
end if;
if(r_pwm_counter=r_max_count) then
r_pwm_counter <= to_unsigned(0,N);
else
r_pwm_counter <= r_pwm_counter + 1;
end if;
end if;
end if;
end process p_state_out;
end rtl;
квадратурный декодер например (по ссылке можно купить для "тренировки") (реализация учитывает направление вращения):
Код
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity QuadratureDecoder is
Port ( QuadA : in STD_LOGIC;
QuadB : in STD_LOGIC;
Clk : in STD_LOGIC;
Position : out STD_LOGIC_VECTOR (7 downto 0));
end QuadratureDecoder;
architecture Behavioral of QuadratureDecoder is
signal QuadA_Delayed: unsigned(2 downto 0) := "000";
signal QuadB_Delayed: unsigned(2 downto 0) := "000";
signal Count_Enable: STD_LOGIC;
signal Count_Direction: STD_LOGIC;
signal Count: unsigned(7 downto 0) := "00000000";
begin
process (Clk)
begin
if Clk='1' and Clk'event then
QuadA_Delayed <= (QuadA_Delayed(1), QuadA_Delayed(0), QuadA);
QuadB_Delayed <= (QuadB_Delayed(1), QuadB_Delayed(0), QuadB);
if Count_Enable='1' then
if Count_Direction='1' then
Count <= Count + 1;
Position <= conv_std_logic_vector(Count, 8);
else
Count <= Count - 1;
Position <= conv_std_logic_vector(Count, 8);
end if;
end if;
end if;
end process;
Count_Enable <= QuadA_Delayed(1) xor QuadA_Delayed(2) xor QuadB_Delayed(1)
xor QuadB_Delayed(2);
Count_Direction <= QuadA_Delayed(1) xor QuadB_Delayed(2);
end Behavioral;
или энкодер в плис это обычный счетчик импульсов...
Далее добавляем двупортовую память в которую будем писать данные для выполнения и конфигурирования PWM
В первый порт пишем принятые данные по UART (вы писали),
я предлагаю SPI (не требуется синхронизации приемника и передатчика)С второго порта читаем данные и выдаем на PWM - результат контролируем с помощью квадратурного декодера (в реализации обычный компаратор)
Вместо двупортовой памяти можно взять двуклоковое фифо
Как в плис сделать из одного модуля три думаю догадаетесь

Если хотите внешний MCU то предлагаю сделать соединение с ПЛИС с помощью external memory interfacе, т.е чтобы MCU видело ПЛИС как свою память ОЗУ + пару пинов для организации обмена прерываниями(окончанием работы(выполнения команды и др)) тогда в ПЛИС делаете двойной буфер и будет отличное решение Возможно не понадобится делать протокол обмена (парсер как Вы это назвали)
Как то так...