国产W806 SPI主机/从机驱动程序

一段时间芯慌后国外芯片价格飙升,国内芯片厂突然崛起;乘此机会使用了该芯片做了一批产品,经过一段时间测试芯片稳定性还可以,工作在电磁环境较差的电源监控中没有出现复位死机现象。

关于该国产芯片资料实在是很少,官方对该芯片的pdf 寄存器描述非常简单;

SPI从机驱动程序:

void slave_spiInit(void)
{
	__HAL_RCC_SPI_CLK_ENABLE();// enable SPI clk
	// SPI GPIO MAP ...
	__HAL_AFIO_REMAP_SPI_CS(GPIOB,GPIO_PIN_4);//NSS
	__HAL_AFIO_REMAP_SPI_CLK(GPIOB,GPIO_PIN_24);//SCLK
	__HAL_AFIO_REMAP_SPI_MOSI(GPIOB,GPIO_PIN_26);//MOSI
	__HAL_AFIO_REMAP_SPI_MISO(GPIOB,GPIO_PIN_25);//MISO
	
	WRITE_REG(SPI->CH_CFG,(1<<22));// clear fifo 
	WRITE_REG(SPI->SPI_CFG,((1<<16)|//1’b1 spi输出一直有驱动,即使没有数据传输
							(1<<1)|//1’b1:传输模式 B
							(1<<0)));//1’b1 SCK IDLE 时为 1
    //补上:
    WRITE_REG(SPI->CH_CFG,(SPI_CH_CFG_RXON | SPI_CH_CFG_TXON)); // enable spi 
}

void slave_Send(uint32_t *dat, int len)
{
	while(len--){
		while((READ_REG(SPI->STATUS) & 0x3F)>=32){;}// 
		WRITE_REG(SPI->TXDATA, (uint32_t)*dat++);
	}
}

int slave_Recv(uint32_t *dat,int len)
{
	uint32_t rxfifo_count =READ_REG(SPI->STATUS);
	rxfifo_count =(rxfifo_count>>6)&0x3f;
	rxfifo_count>>=2;
	if(rxfifo_count>=len){
		for(int i=0;i<rxfifo_count;i++){
			*dat++=SPI->RXDATA;
		}
	}
return rxfifo_count;
}

void main(void)
{
    int fifolen =0;
    uint8_t fifoDat[32]={0};
    slave_spiInit();
    do{
        fifolen =slave_Recv((uint32_t*)fifoDat,3);// SPI 收发必须是32 bit !
        if(fifolen>=3){//3*4byte =12 Byte
            slave_Send((uint32_t*)fifoDat,3);
        }
    }while(1);
}

SPI主机驱动程序:

void master_spiInit(void)
{
	__HAL_RCC_SPI_CLK_ENABLE();// enable SPI clk
	// SPI GPIO MAP ...
	__HAL_AFIO_REMAP_SPI_CS(GPIOB,GPIO_PIN_4);//NSS
	__HAL_AFIO_REMAP_SPI_CLK(GPIOB,GPIO_PIN_24);//SCLK
	__HAL_AFIO_REMAP_SPI_MOSI(GPIOB,GPIO_PIN_26);//MOSI
	__HAL_AFIO_REMAP_SPI_MISO(GPIOB,GPIO_PIN_25);//MISO
	
	SPI->CH_CFG=(1<<22);// clear fifo 
	SPI->SPI_CFG =(1<<2);//master style
	uint32_t div =40000000/(900000*2) - 1;//SPI =900Khz
	SPI->CLK_CFG =div;//设置SPI输出时钟
	SPI->CH_CFG|=(SPI_CH_CFG_RXON | SPI_CH_CFG_TXON); // enable spi 
}

//返回接收长度
int master_SendRecv(uint8_t *rev ,uint8_t *snd ,uint16_t tlen)
{
	uint32_t* snd32  ,*rev32 =(uint32_t*)rev;
	uint32_t tx_rx_bitlen,clen=tlen ,rlen=tlen;

	snd32 =(uint32_t*)snd;
	uint16_t fifo_tfree;
	SPI->CH_CFG|=(1<<22);// clear fifo 
	do{
		//step 1 ,确定时钟个数
		if(tlen>1020){
			clen =1020;
			tlen-=1020;
		}else{
			clen=tlen;
			tlen =0;
		}
		tx_rx_bitlen =SPI->CH_CFG;
		tx_rx_bitlen&=~((uint32_t)0xffff<<3);
		tx_rx_bitlen|=(clen*8)<<3;
		SPI->CH_CFG=tx_rx_bitlen ;
		//step 2 ,写入数据到SPI
		SPI->CH_CFG|=(1<<0);//启动SPi
		do{
			//step 3 ,写入数据到SPI
			fifo_tfree =(32-(SPI->STATUS& 0x3f))/4;//确定fifo 大小
			while(fifo_tfree&&clen){
				SPI->TXDATA = *snd32++;
				clen =(clen>4)?clen-4:0;
				fifo_tfree--;
			}
			//step 4 ,等待SPI空闲
			while(SPI->STATUS&(1<<12)){;}
			//step 5 ,接收数据	
			fifo_tfree =((SPI->STATUS>>6)&0x3f)/4;
			while(fifo_tfree--){
				*rev32++ = SPI->RXDATA;
			}
		}while(clen>0);
	}while(tlen>0);
	//step 6 ,接收残余数据
	if(rev32!=NULL&&(rlen&0x3)){//未满4byte
		*rev32++ = SPI->RXDATA;
	}
return rlen;
}

int main(void)
{
    uint8_t txbuf[1024],rxbuf[1024];
    master_spiInit();
    do{
        master_SendRecv(rxbuf,txbuf,25);
    }while(1);
}

SPI主机驱动波形:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值