[verilog] STM32 SPI 连接 EPM240T100C5N 数据不稳定

[复制链接]
413|13
 楼主 | 2020-1-13 21:09 | 显示全部楼层 |阅读模式
发送和接受到的数据经常错位或卡顿 导致不稳定
STM32F103VE   SPI 速度 9M
EPM240T100C5N 时钟 50M
应该时 CPLD SPI 接口程序问题 各位大哥帮忙看看

/***********************************************************************
     ****************** name:SPI_Slaver_Driver **************
            ********** author:made by zzuxzt **********
     ****************** time:2014.4.29 **********************
***********************************************************************/
//use SPI 3 mode,CHOL = 1,CHAL = 1
module spi(        input clk,
                        input rst_n,
                        input CS_N,
                        input SCK,
                        input MOSI,
                        output reg MISO,
                        input [7:0] txd_data,
                        output reg [7:0] rxd_data,
                        output rxd_flag);        /*recieve done,please transmit data*/

//-------------------------capture the sck-----------------------------   
reg sck_r0,sck_r1;
wire sck_n,sck_p;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            sck_r0 <= 1'b1;   //sck of the idle state is high
            sck_r1 <= 1'b1;
        end
    else
        begin
            sck_r0 <= SCK;
            sck_r1 <= sck_r0;
        end
end

assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge
assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge

//-----------------------spi_slaver read data-------------------------------
reg rxd_flag_r;
reg [2:0] rxd_state;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            rxd_data <= 1'b0;
            rxd_flag_r <= 1'b0;
            rxd_state <= 1'b0;
        end
    else if(sck_p && !CS_N)   
        begin
            case(rxd_state)
                3'd0:begin
                        rxd_data[7] <= MOSI;
                        rxd_flag_r <= 1'b0;   //reset rxd_flag
                        rxd_state <= 3'd1;
                      end
                3'd1:begin
                        rxd_data[6] <= MOSI;
                        rxd_state <= 3'd2;
                      end
                3'd2:begin
                        rxd_data[5] <= MOSI;
                        rxd_state <= 3'd3;
                      end
                3'd3:begin
                        rxd_data[4] <= MOSI;
                        rxd_state <= 3'd4;
                      end
                3'd4:begin
                        rxd_data[3] <= MOSI;
                        rxd_state <= 3'd5;
                      end
                3'd5:begin
                        rxd_data[2] <= MOSI;
                        rxd_state <= 3'd6;
                      end
                3'd6:begin
                        rxd_data[1] <= MOSI;
                        rxd_state <= 3'd7;
                      end
                3'd7:begin
                        rxd_data[0] <= MOSI;
                        rxd_flag_r <= 1'b1;  //set rxd_flag
                        rxd_state <= 3'd0;
                      end
                default: ;
            endcase
        end
end


//--------------------capture spi_flag posedge--------------------------------
reg rxd_flag_r0,rxd_flag_r1;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            rxd_flag_r0 <= 1'b0;
            rxd_flag_r1 <= 1'b0;
        end
    else
        begin
            rxd_flag_r0 <= rxd_flag_r;
            rxd_flag_r1 <= rxd_flag_r0;
        end
end

assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;   

//---------------------spi_slaver send data---------------------------
reg [2:0] txd_state;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            txd_state <= 1'b0;
        end
    else if(sck_n && !CS_N)
        begin
            case(txd_state)
                3'd0:begin
                        MISO <= txd_data[7];
                        txd_state <= 3'd1;
                      end
                3'd1:begin
                        MISO <= txd_data[6];
                        txd_state <= 3'd2;
                      end
                3'd2:begin
                        MISO <= txd_data[5];
                        txd_state <= 3'd3;
                      end
                3'd3:begin
                        MISO <= txd_data[4];
                        txd_state <= 3'd4;
                      end
                3'd4:begin
                        MISO <= txd_data[3];
                        txd_state <= 3'd5;
                      end
                3'd5:begin
                        MISO <= txd_data[2];
                        txd_state <= 3'd6;
                      end
                3'd6:begin
                        MISO <= txd_data[1];
                        txd_state <= 3'd7;
                      end
                3'd7:begin
                        MISO <= txd_data[0];
                        txd_state <= 3'd0;
                      end
                default: ;
            endcase
        end
end

endmodule

使用特权

评论回复
 楼主 | 2020-1-13 21:11 | 显示全部楼层
STM32

void SPI3_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;
  
        RCC_APB2PeriphClockCmd(        SPI3_PORT_RCC , ENABLE );       
    RCC_APB1PeriphClockCmd(SPI3_RCC,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

        GPIO_InitStructure.GPIO_Pin = SPI3_CLK_PIN | SPI3_MOSI_PIN | SPI3_MISO_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(SPI3_CLK_PORT, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = SPI_CS_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(SPI_CS_PORT, &GPIO_InitStructure);

        GPIO_SetBits(SPI3_CLK_PORT,SPI3_CLK_PIN|SPI3_MOSI_PIN|SPI3_MISO_PIN|SPI_CS_PIN);

        SPI_InitStructure.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
        SPI_InitStructure.SPI_Mode              = SPI_Mode_Master;                //设置SPI工作模式:设置为主SPI
        SPI_InitStructure.SPI_DataSize          = SPI_DataSize_8b;                //设置SPI的数据大小:SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL              = SPI_CPOL_High;                //选择了串行时钟的稳态:时钟悬空高
        SPI_InitStructure.SPI_CPHA              = SPI_CPHA_2Edge;        //数据捕获于第二个时钟沿
        SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;                //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;                //定义波特率预分频的值:波特率预分频值为256
        SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial     = 7;        //CRC值计算的多项式
        SPI_Init(SPI3, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

        SPI_Cmd(SPI3, ENABLE); //使能SPI外设
       
//        SPI1_ReadWriteByte(0xff);//启动传输                 
}  

//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI3_ReadWriteByte(u8 TxData)
{               
        u8 retry=0;                                        
        while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
                {
                retry++;
                if(retry>200)return 0;
                }                          
        SPI_I2S_SendData(SPI3, TxData); //通过外设SPIx发送一个数据
        retry=0;

        while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET)//检查指定的SPI标志位设置与否:接受缓存非空标志位
                {
                retry++;
                if(retry>200)return 0;
                }                         
        return SPI_I2S_ReceiveData(SPI3); //返回通过SPIx最近接收的数据                                            
}

使用特权

评论回复
 楼主 | 2020-1-13 21:13 | 显示全部楼层
SPI 硬件接口是通过FPC 10CM 直接连接 好像应该添加电阻 测试阶段影响不大吧

使用特权

评论回复
| 2020-1-13 23:10 | 显示全部楼层
89C51RX 发表于 2020-1-13 21:13
SPI 硬件接口是通过FPC 10CM 直接连接 好像应该添加电阻 测试阶段影响不大吧

如果确定逻辑没有问题  但是感觉数据还是莫名的不对
那就考虑是电平匹配问题  最好串接电阻

使用特权

评论回复
 楼主 | 2020-1-13 23:15 | 显示全部楼层
zhangmangui 发表于 2020-1-13 23:10
如果确定逻辑没有问题  但是感觉数据还是莫名的不对
那就考虑是电平匹配问题  最好串接电阻 ...

数据有时正常 有时不正常 两端都是3.3v 电位 影响大吗

使用特权

评论回复
 楼主 | 2020-1-13 23:18 | 显示全部楼层
zhangmangui 发表于 2020-1-13 23:10
如果确定逻辑没有问题  但是感觉数据还是莫名的不对
那就考虑是电平匹配问题  最好串接电阻 ...

可以帮吗看看程序 有没有问题吗

使用特权

评论回复
| 2020-1-15 21:26 | 显示全部楼层
89C51RX 发表于 2020-1-13 23:15
数据有时正常 有时不正常 两端都是3.3v 电位 影响大吗

等电位3.3V应该没问题  

使用特权

评论回复
| 2020-1-15 21:45 | 显示全部楼层
verilog那边最好仿真 抓一下时序吧

使用特权

评论回复
| 2020-1-15 23:48 | 显示全部楼层
楼主搞定了没?

使用特权

评论回复
 楼主 | 2020-1-17 22:02 | 显示全部楼层

没有啊 电阻加了 没效果啊

使用特权

评论回复
 楼主 | 2020-1-17 22:03 | 显示全部楼层
zhangmangui 发表于 2020-1-15 21:45
verilog那边最好仿真 抓一下时序吧

我是 刚学 能力还不行

使用特权

评论回复
 楼主 | 2020-1-17 22:06 | 显示全部楼层
zhangmangui 发表于 2020-1-15 21:45
verilog那边最好仿真 抓一下时序吧

可以帮忙 研究下吗  有偿也可QQ 564412039

使用特权

评论回复
| 2020-1-19 18:06 | 显示全部楼层
程序都是自己编写的?或者各论坛搜索一下,看看别人共享的的代码,对比是否有差异

先用其它板来确认MCU部分的SPI没有问题,硬件上,注意电源部分的滤波……有时候碰到很头疼的问题,可能只是因为一个小小的疏忽

使用特权

评论回复
| 2020-1-21 19:51 | 显示全部楼层
STM32的SPI配置四种模式都试一下

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /2 下一条

在线客服 快速回复 返回顶部 返回列表