我首先使用stm32通过spi发送数据到cpld,cpld处理数据后发回。问题的关键是,cpld中的程序的工作机制是这样的:我接受一切数据,甚至不区分什么帧头帧尾,什么位长。我cpld做的工作就是将收到的数据编码(收到的所有数据甚至空闲电平)都编码,经过低速光纤传输后在另一端把数据解码出来,包括什么空闲电平,帧头帧尾(当然,spi没用到帧头帧尾)。然后在通过spi传回给stm32。
可以看出,这种工作机制是很符合异步串行通信,但是spi是同步串行通信。所以stm32的spi预分频数只要超过了64,就无法接受到正确数据。通过示波器,我发现问题出在(看图)
从图上可以看出,在SCK(绿色波形,黄色波形是stm32的mosi发送数据)上升沿时,由于返回的数据和SCK不同步,导致SCK上升沿时不能每次都扫描到正确的电平。我认为解决的方法是:1、由于CPLD的时钟是50Mhz,而spi速度最高才是36/2=18M,只要将MISO(紫色波形)左移半个SCK,就可以保证SCK每次都扫描到正确的电平。
2、或者将收到的mosi的黄色波形数据收到后先不编码,左移半个SCK,然后再发送到编码。如图
但是,CPLD里的编码解码程序是别人写的,我不会改,我想单纯的在cpld的MoSi端,定义一个寄存器,然后在SCK的下降沿发送数据(stm32设置的是上升沿SCK检测电平)这样就能实现左移半个SCK。可是,写程序遇到了麻烦。
一个process中不能同时检测两个时钟沿。
可是我就是要在50Mhz的时钟下,检测spi的SCK的上升沿和下降沿啊。上升沿把数据存入寄存器。下降沿将数据发送到后面的编码器(别人的数据,我不会改,只能是保证它的不变,然后在前面加一个小模块,将小模块的输出当成它原来的输入给它)。
我写vhdl的思路是,第一个8bit数据,将数据存入a寄存器,第二个8bit数据传输周期,将数据存入b寄存器,同时在下降沿把a寄存器中数据发送到后面模块的输入,第三个8bit数据传输周期,将数据存入a寄存器,将b寄存器中数据发送到后面模块。这样不就同步了吗。
贴出来我写的那一些vhdl,帮忙告诉我怎么写,或者有解决上面问题的新思路。(我认为我上面的思路应该有逻辑错误,但我想了好久想不出来)谢谢了
signal TX:std_logic;
signal a:std_logic:='0';
signal b:std_logic:='0';
signal rx_shift_reg:std_logic_vector(7 downto 0):=(others=>'0');
signal rx_shift_reg_2:std_logic_vector(7 downto 0):=(others=>'0');
signal shift_cnt:std_logic_vector(3 downto 0):=(others=>'0');
signal shift_cnt_2:std_logic_vector(3 downto 0):=(others=>'0');
signal cnt:std_logic_vector(3 downto 0):=(others=>'0');
signal cnt_2:std_logic_vector(3 downto 0):=(others=>'0');
if rising_edge(spi_sck) then
if(a='1')then
rx_shift_reg<=rx_shift_reg(6 downto 0)& spi_din;
shift_cnt<=shift_cnt+1;
if(shift_cnt=x"07")then
b<='1';
a<=not a;
end if;
else
rx_shift_reg_2<=rx_shift_reg_2(6 downto 0)& spi_din;
shift_cnt_2<=shift_cnt_2+1;
if(shift_cnt_2=x"07")then
b<='0';
a<=not a;
end if;
end if;
end if;
if(b='1')then
if falling_edge(spi_sck) then
cnt<=cnt+1;
if(cnt=x"00")then
TX<=rx_shift_reg(7);
else
rx_shift_reg<=rx_shift_reg(6 downto 0)&'0';
TX<=rx_shift_reg(6);
if(cnt=x"07")then
cnt<=x"00";
end if;
end if;
end if;
else
if falling_edge(spi_sck) then
cnt_2<=cnt_2+1;
if(cnt_2=x"00")then
TX<=rx_shift_reg_2(7);
else
rx_shift_reg_2<=rx_shift_reg_2(6 downto 0)&'0';
TX<=rx_shift_reg_2(6);
if(cnt_2=x"07")then
cnt_2<=x"00";
end if;
end if;
end if;
end if;
谢谢,头已炸