Stm32Motor 发表于 2023-12-19 15:13:55

CDBUS调试过程总结

第一使用CDBUS,感谢版主dukelec热心指导,调试完成,分享调试过程中遇到的问题。
1:使用STM32cubemX生成SPI初始化代码,读寄存器成功,写寄存器不成功,在版主dukelec的指导下发现写寄存器的时候没有加0x80,加上0x80后写寄存器正常;
2:在使用HAL库HAL_SPI_TransmitReceive函数时,无接收数据时把接收缓存区指针设置为空,导致没有发送数据,修改为HAL_SPI_Transmit和HAL_SPI_Receive后能通道;
3:测试发现,上电后第一次收到数据不对,经版主dukelec指点发现是由于初始化的时候读了一遍所有寄存器(调试1问题的时候把所以寄存器读出来),导致RX指针不对,删除读所以寄存器代码后,上电后第一次数据接收正常;
4:1,2,3是使用10M波特率,将波特率调整到20M后偶尔能收到数据,经版主dukelec检测发现是由于bridge的波特率设置为20M时偏差教大,bridge与我的板子调整到25M后,通信正常;
5:查看HAL SPI发送与接收相关函数,发现很复杂,使用寄存器方式重写读写函数,测试发现只写不接收时也须要读DR寄存器(__HAL_SPI_CLEAR_OVRFLAG(hspi));
6:使用串口助手连续发数据,发现有时会收不到数据,经主dukelec指点后,改成在主循环读中段引脚电平,为低表示须要处理数据(版言主解析为数据太快时,中段中还没有读完数据又收到下一帧数据,导致STM32无法过中断,STM32只能边沿触发中断).
以下为寄存器操作SPI代码:
void SPI_ReadWriteByte(SPI_TypeDef *spi,unsigned char *pTxData, uint8_t txlen,unsigned char*pRxData, uint8_t rxlength)//寄存器版本
{      
        //volatile unsigned char tmpreg;
        unsigned short TxXferCount,RxXferCount;
        unsigned char *pRxBuffPtr= pRxData;
        unsigned char *pTxBuffPtr= pTxData;
        unsigned char txallowed = 1U;
        __IO unsigned int tmpreg_ovr = 0x00U;
       
        if(txlen>0)
                TxXferCount=txlen;
        else
                TxXferCount=rxlength;
       
        RxXferCount=rxlength;

        //如果 FIFO 占用水平大于或等于 1/4(8 位),将生成 RXNE 事件
        SET_BIT(spi->CR1, SPI_CR1_SPE);
        SET_BIT(spi->CR2, SPI_RXFIFO_THRESHOLD);

        while((TxXferCount > 0) || (RxXferCount > 0))
        {
          if(txallowed && ((spi->SR & SPI_FLAG_TXE) == SPI_FLAG_TXE) && (TxXferCount > 0))
          {
             if(txlen>0)
                {
                        *((__IO unsigned char *)(&spi->DR)) = (*pTxBuffPtr++);
               }
               else
                {
                        *((__IO unsigned char *)(&spi->DR))=0x00;
               }
                               
                txallowed = 0U;
          }
           if((spi->SR & SPI_FLAG_RXNE) == SPI_FLAG_RXNE)
           {
               TxXferCount--;
               txallowed = 1U;
                if(RxXferCount > 0)
                {
                        RxXferCount--;
                        (*pRxBuffPtr++) =*(__IO unsigned char *)&spi->DR;
             }
              else
              {
                        tmpreg_ovr=*(__IO unsigned char *)&spi->DR;
                        tmpreg_ovr=*(__IO unsigned char *)&spi->SR;
                        UNUSED(tmpreg_ovr);   
                }
           }
   }      
}

以下为CDBUS初始化代码,12M晶振,低速波特率1M,高速波特率25M
void CdBusInit(void)
{
        uint8_t version=CdBusReadReg(VERSION);
       
        CdBusWriteReg(CLK_CTRL, 0x80);    // Soft reset
        CdBusWriteReg(PLL_ML,0x30);   //取默认值      
//CdBusWriteReg(PLL_OD_MH,0x00);//取默认值      
CdBusWriteReg(PLL_N,0x02);   //取默认值
        CdBusWriteReg(PLL_CTRL, 0x10);    //启用PLL
        HAL_Delay(10);
        CdBusWriteReg(CLK_CTRL, 0x01);    //时钟选择 PLL 12M晶振  sysclk=60Mhz
       
        CdBusWriteReg(PIN_RE_CTRL, 0x10); // Set RE_N pin to low
        CdBusWriteReg(SETTING, 0x11);   // Enable push-pull output
        CdBusWriteReg(FILTER, 0x0c);      // Set FILTER
        // Set baudrates
        CdBusWriteReg(DIV_LS_L, 74);      // 1 Mbps @75MHz sysclk
        CdBusWriteReg(DIV_LS_H, 0);
       
        CdBusWriteReg(DIV_HS_L, 2);       // 25 Mbps @75MHz sysclk75/(2+1)=75/3=25MHz
        CdBusWriteReg(DIV_HS_H, 0);
       
        CdBusWriteReg(RX_CTRL, 0x11);   // Reset RX buffers and flags (optional)
        //Enable interrupts (optional)
        CdBusWriteReg(INT_MASK, BIT_FLAG_TX_ERROR | BIT_FLAG_RX_ERROR | BIT_FLAG_RX_LOST | BIT_FLAG_RX_PENDING);
}

Stm32Motor 发表于 2023-12-19 15:15:18

发送数据函数:
uint8_t CdBusSendData(uint8_t src_addr,uint8_t des_addr,uint8_t *buf,uint8_t length)
{
        CD_BUS_CS_L;
       
        uint8_t txbuf={0};
        txbuf=TX+0x80;
        txbuf=src_addr;
        txbuf=des_addr;
        txbuf=length;
        SPI_ReadWriteByte(SPI3,txbuf,4,NULL,0);
        SPI_ReadWriteByte(SPI3,buf,length,NULL,0);
        CD_BUS_CS_H;
       
        while(!(CdBusReadReg(INT_FLAG) & 0x20)); // Make sure we can successfully switch to the next page
        CdBusWriteReg(TX_CTRL, 0x03); // Trigger send by switching TX page
       
        return 0;
}

Stm32Motor 发表于 2023-12-19 15:15:37

接收数据函数:
void CdBusReadChunk(uint8_t *buf,uint8_t length)
{
        uint8_t txbuf={0};
        txbuf=RX;
       
        CD_BUS_CS_L;
        SPI_ReadWriteByte(SPI3,txbuf,1,NULL,0);
        SPI_ReadWriteByte(SPI3,NULL,0,buf,length);
        CD_BUS_CS_H;
}

void CdBusRecvData()
{
        if(CdBusReadReg(INT_FLAG) & BIT_FLAG_RX_PENDING)
        {
                memset(rxbuf,0,256);
                CdBusReadChunk(rxbuf,3);
                CdBusReadChunk(rxbuf+3,rxbuf);
                CdBusWriteReg(RX_CTRL, 0x03);
                bRecvData=1;
                DataProcess();
                //printinfo("recv data");
                CdBusSendData(0x0c,0x00,&rxbuf,rxbuf);
        }
}

leafstamen 发表于 2023-12-19 15:46:33

如果不使用类似版主的CDCTL01A这种软件的实现,有没有可能通过搭电路来检测485芯片前后的电平是否对应,来实现相同的功能呢?

Stm32Motor 发表于 2023-12-19 15:54:10

芯片很便宜,{:lol:}

dukelec 发表于 2023-12-19 16:06:53

其实可以考虑移植我现有的代码:

hal 查询版本:
https://github.com/dukelec/cdnet/blob/master/dev/cdctl.c

hal dma 版本:
https://github.com/dukelec/cdnet/blob/master/dev/cdctl_it.c

寄存器 + dma 版本的:
https://github.com/dukelec/cdbus_bridge/blob/master/fw_bridge/usr/cdctl_fast.c

Stm32Motor 发表于 2023-12-19 16:10:58

多谢版主的汤圆。

zzh90513 发表于 2023-12-19 16:12:22

谢谢分享!很快我也要试试这个芯片

Stm32Motor 发表于 2023-12-19 16:12:38

下午用电脑通过bridge以25M的速度每隔1MS发10字节数据给我的板子,板子收到后回传收的数据,测试500W+数据没有丢失.

Stm32Motor 发表于 2023-12-19 16:14:57

zzh90513 发表于 2023-12-19 16:12
谢谢分享!很快我也要试试这个芯片
(引用自8楼)

SPI熟悉的话,就很快,我都是卡在HAL的SPI里面。
页: [1]
查看完整版本: CDBUS调试过程总结