初学小白,说得不对的地方欢迎大家指教,谢谢!
题外话:最近突然来了兴趣想学stm32,在某宝搞了块核心版,学习过程中又在某宝闲逛的时候看了了一个小模块,si4702收音模块,哦豁,兴奋了。可能跟工作有关吧,总想弄个收音机,以前弄过基于51的rda5820,tea5767,这回换stm32+si4702,芯片到手后照例找店家要例程,店家告诉我没有,只有一张引脚图,突然懵逼了,怎么办,硬上吧,不就是看数据手册吗,我有谷歌翻译。
正题开始了。开始了我的表演。
从店家告诉我没有例程后,我就开始了自己编写,模块引脚图如下:
参照官方数据手册对比
模块2脚是SDIO,10脚是SCLK,9脚这个置位使能端应该是RST,模块分析完毕,连上stm32核心版,接下来开始写程序了,怎么写?只有看数据手册了,手册上4.9 Reset, Powerup, and Powerdown介绍了怎么上电并选择2线或者3线操作模式,这模块一看就只能2线操作啊,那就先写复位,在RST上升沿时保持SDIO为低,且SCLK为高。如下:
static void si4702_reset(void) //4702复位,选择2线模式
{
SI_SDIO_L;
SI_RST_L;
SI_SCL_H; //手册上有句话:复位期间必须保持SCLK为高,且至少持续到第一个开始信号
delay_ms(300);
SI_RST_H;
delay_ms(150);
SI_SDIO_H;
delay_ms(10);
}
上电了,就准备写入或者读取数据了,看时序图
有开始,ACK,结束,这不是IIC吗?不知道IIC兼容不,手册上也没有明确表示支持IIC,我也没试,就参照官方的例程写的,关于写和读,器件地址是0010000b+R/W,最后一位是读写标志位,1为读,0为写,芯片总共有16个16位的寄存器,从00H到0FH,写入是从寄存器02H开始,每次1个字节,高位在前,低位在后,直到0F低8位写完后,绕回到00H。读取顺序是从0A开始,每次1个字节,高位在前,低位在后,到0FH,再到00H。
关于写入,芯片收到开始信号后就可以连续写入,每个字节后芯片给个ACK(SDIO=0),直到收到停止信号结束。代码如下:
开始信号,u8 addr:芯片地址,u8 rw:读写标志1或0
static void si4702_start(u8 addr, u8 rw) //开始,rw读写标志,0写,1读
{
signed char i;
SI_SCL_H;
si4702_sdio_out();
SI_SDIO_H;
delay_us(2);
SI_SDIO_L;
delay_us(2);
SI_SCL_L;
addr = (addr & 0xfe) | (rw & 0x01);
for(i=7;i>=0;i--)
{
SI_SCL_L;
delay_us(2);
if(((addr >> i) & 0x01) > 0) SI_SDIO_H;
else SI_SDIO_L;
delay_us(2);
SI_SCL_H;
delay_us(2);
}
//wait ack
SI_SCL_L;
si4702_sdio_in(); //这里因为配置SDIO为上拉输入模式,所以SDIO=1
delay_us(2);
SI_SCL_H;
delay_us(2);
if(SI_SDIO_IN != RESET) printf("ack error!\r\n"); //判断是否收到4702应答,自行优化
}
停止传输
static void si4702_stop(void) //数据传输停止
{
SI_SCL_L;
delay_us(2);
si4702_sdio_out();
SI_SDIO_L;
delay_us(2);
SI_SCL_H;
SI_SDIO_H;
}
写入一个字节, u8 wdata:需要写入的内容
ps:这里有个坑,stm32 char 默认是从0-255,signed char -127~128。说多了都是泪。
static void si4702_write_byte(u8 wdata) //发送一个字节
{
signed char i;
si4702_sdio_out();
for(i=7;i>=0;i--)
{
SI_SCL_L;
delay_us(2);
if(((wdata >> i) & 0x01) > 0) SI_SDIO_H;
else SI_SDIO_L;
delay_us(2);
SI_SCL_H;
delay_us(2);
}
//wait ack
SI_SCL_L;
si4702_sdio_in();
delay_us(2);
SI_SCL_H;
delay_us(2);
if(SI_SDIO_IN != RESET) printf("ack error\r\n"); //判断是否收到4702应答,自行优化
}
连续写入多个字节,u8 *data_out:8位的数组存放需要写入的内容,u8 num:写入的次数,16个16位的寄存器,一次8位,全部写完需要写入32次
static void si4702_write(u8 num, u8 *data_out) //向4702写入数组里的数据
{
si4702_start(SI_SIADDR,SI_WRITE);
while(num--)
{
si4702_write_byte(*data_out++);
}
si4702_stop();
}
写入有了,接下来就是读取了,每读完一个字节需要mcu给芯片一个ACK(SDIO=0)是否继续读。代码如下:
读取一个字节,u8 num_bytes:是否给出ACK信号,为0是表示不发送
static u8 si4702_read_byte(u8 num_bytes) //读取一个字节
{
signed char i;
u8 rdata=0;
si4702_sdio_in();
for(i=7;i>=0;i--)
{
SI_SCL_L;
delay_us(1);
delay_us(2);
SI_SCL_H;
delay_us(2);
rdata = ((rdata<<1) | SI_SDIO_IN);
}
//send ack
si4702_sdio_out();
SI_SCL_L;
delay_us(2);
if(num_bytes != 0) SI_SDIO_L; //连续读取需要mcu给出应答,参照数据手册
else SI_SDIO_H;
delay_us(2);
SI_SCL_H;
delay_us(2);
SI_SCL_L;
return rdata;
}
连续读取,u8 *data_in:存放数据的数组,u8 num:读取的次数,16个16位的寄存器,一次8位,全部读完需要读取32次
static void si4702_read(u8 num, u8 *data_in) //读取4702寄存器数据并存入数组中
{
si4702_start(SI_SIADDR,SI_READ);
while(num--)
{
*data_in++ = si4702_read_byte(num);
}
si4702_stop();
}
写入和读取都有了,剩下的就是寄存器配置了,参照手册自行配置了,以上所有配置都已调试好,暂未发现问题,有不对的地方欢迎大家指正,谢谢!
完整程序:https://download.csdn.net/download/u014040765/19731407?spm=1001.2014.3001.5503
资源包里除了驱动程序,还包含了si4702/02-c19数据手册,AN332官方编程指导和AN332官方源码。
最后放一张垃圾图