- 积分
- 1668
- 在线时间
- 2673 小时
- 最后登录
- 2025-2-8
- 阅读权限
- 70
- 精华
- 0
 
- UID
- 897598
- 帖子
- 1550
- 精华
- 0
- 经验
- 1668 点
- 金钱
- 1451 ¥
- 注册时间
- 2021-2-4
|
本帖最后由 mchoi518 于 2023-11-9 12:36 编辑
经过一周潜心研究单片机,终于做完了我的第一个软控DAC,与手里其它几个解码器对比如下。
先上ES9038Q2M解码板电路图,
ES9038Q2M芯片是tb买的36元一个,帮我看看是不是打磨的~
从左到右分别是ES9038Q2M, ES9018K2M, PCM1794A。
三个解码板用的IV是同一块板。
RMAA测试结果。确实指标高的测试结果也高,我用在低通炮前面,所以动态最高的9038适合我
因为这个解码器用在低通,SPDIF 24bit 48khz信号上,所以只对比24bit 48khz。
下面上几个RMAA截图
下面是STM8S103F3P6用硬件I2C的新手教程,也是我几天刻苦专研的成果,对老手来说可能啥都不是,但对于没接触过单片机的人来说还是很难的,我争取让新手尽量少走弯路。
特别感谢“拥抱STM8”那个帖子的作者,因为程序主要是参照了他的思路,
可能他那个用的早年的库文件,有些参数语句报错,我给大家最新版库文件和我重新写的完整代码。
程序实现目标:能解码SPDIF信号,外加SPDIF信号锁定点灯功能!
1. 开发环境准备
开发工具用 IAR for STM8,烧录器在tb买个st link v2,带SWIM接口的,十多块钱。
其他不需要,有的人喜欢用IAR和STVP免费烧录工具,但是IAR FOR STM8集成了debug和烧录功能,收费的破解了用才爽~
IAR for STM8 3.11.2官方最新下载地址,需要注册账号:
https://www.iar.com/products/arc ... workbench-for-stm8/
破解文件下载:
链接:https://pan.baidu.com/s/1BbJDWGLcVzpYb4fGqwi7CA
提取码:68l7
IAR安装和破解,stlink教程:
https://zhuanlan.zhihu.com/p/399177651?utm_id=0
IAR 创建工程和设置方法:
https://zhuanlan.zhihu.com/p/99345097?utm_id=0
IAR debug和下载芯片方法:
https://blog.csdn.net/qq_28435683/article/details/115353156
STM8S的官方最新库文件下载地址,需要注册账号:
https://www.st.com/en/embedded-software/stsw-stm8069.html
找 STSW-STM8069 STM8S/A Standard peripheral library, 点“Get latest”按钮
2. 程序代码
可以直接复制了使用,一定要用最新的库文件。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "stm8s.h" //基础库文件要写到这里,其他stm8s_clk.c stm8s_gpio.c stm8s_i2c.c不用写,但是一定要加到workspace里面!!
#define DAC_ADDRESS 0x90 //被控制从设备即ES9038Q2M的地址赋值给"DAC_ADDRESS",因为电路中ADDR脚接地了,所以按datasheet地址是0x90
#define GPIO_PINS (GPIO_PIN_3 | GPIO_PIN_2) //定义需要管理的GPIO脚,电路中只用到PD2,PD3脚
uint8_t SPDIF_STATUS; //定义一个8位全局变量,保存解码芯片96号寄存器的读取结果
uint8_t R; //定义一个8位全局变量,用作DEBUG时I2C读取、写入各步骤进行情况跟踪
void Delay(uint16_t nCount) //定义延迟函数,最多延迟65535次循环,差不多0.1秒
{
while (nCount != 0)
{
nCount--;
}
}
void MCU_Init(void) //定义STM8S单片机初始化函数
{
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //设置内部高速时钟16M为主时钟
I2C_Cmd(DISABLE); //I2C关掉
// GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_OUT_OD_HIZ_FAST); //软件I2C用的,咱用硬件I2C,所以这个GPIO初始化咱用不上
// GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_OD_HIZ_FAST);
GPIO_Init(GPIOD, (GPIO_Pin_TypeDef)GPIO_PINS, GPIO_MODE_OUT_PP_HIGH_FAST); //GPIO初始化,GPIOD就是PD开头的引脚,GPIO_PINS上面定义的2和3脚,模式是OUT输出、PP推挽、HIGH高电平
I2C_Init(100000, 0xA0, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16); //I2C初始化,100k速度,给自己一个地址0xA0,占空比,开启ACK,7bit模式,16M时钟
I2C_Cmd(ENABLE); //I2C开启
}
void DAC_Init(void) //定义ES9038Q2M解码芯片初始化函数,通过电路中STM8的PD2和9038的RESETB脚连接,一个低电平后一个高电平对DAC初始化
{
Delay(0xFFFF); //延迟1ms
GPIO_WriteLow(GPIOD, (GPIO_Pin_TypeDef)GPIO_PIN_2); //GPIO输出低电平(PD2引脚)
Delay(0xFFFF); //延迟1ms
GPIO_WriteHigh(GPIOD, (GPIO_Pin_TypeDef)GPIO_PIN_2); //GPIO输出高电平(PD2引脚)
Delay(0xFFFF); //延迟1ms
}
void I2C_Write(uint8_t address,uint8_t data) //硬件I2C写函数定义
{
R=21; //R都是为了DEBUG时,通过R值,了解读写操作卡在哪一步
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); //等待空闲
R=22;
I2C_GenerateSTART(ENABLE); //开启I2C
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)); //等待EV5,主模式
R=23;
I2C_Send7bitAddress(DAC_ADDRESS, I2C_DIRECTION_TX ); //器件地址,从设备地址
while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //等待EV6
R=24;
I2C_SendData(address); //寄存器地址
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //等待传输完成,EV8
R=25;
I2C_SendData(data); //发送数据
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //等待传输完成,EV8_2
R=26;
I2C_AcknowledgeConfig(I2C_ACK_CURR); //使能I2C的应答功能
R=27;
I2C_GenerateSTOP(ENABLE); //关闭I2C总线
R=28;
}
void I2C_Read(uint8_t address) //硬件I2C读函数定义
{
R=1;
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); //等待空闲
R=2;
I2C_GenerateSTART(ENABLE); //开启I2C
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)); //等待EV5,主模式
R=3;
I2C_Send7bitAddress(DAC_ADDRESS, I2C_DIRECTION_TX); //器件地址 从设备地址
while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //等待EV6事件
R=4;
I2C_SendData(address); //寄存器地址
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //等待传输完成
R=5;
I2C_GenerateSTART(ENABLE); //开启I2C
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)); //等待EV5,主模式
R=6;
I2C_Send7bitAddress(DAC_ADDRESS, I2C_DIRECTION_RX); //器件地址 从设备地址
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED)); //等待EV7,接收完成
R=7;
I2C_AcknowledgeConfig(I2C_ACK_NONE); //无应答
while(I2C_GetFlagStatus(I2C_FLAG_RXNOTEMPTY) == RESET); //重置
R=8;
SPDIF_STATUS = I2C_ReceiveData(); //将I2C读取到的值,赋值给SPDIF_STATUS
R=9;
I2C_GenerateSTOP(ENABLE); //关闭I2C总线
R=10;
}
/*以下是ES9038Q2M所有寄存器的描述我抄了一遍手册,包括手册中默认值、<>是与手册不同的、【】是通过I2C_Write和I2C_Read用到的*/
// I2C_Read(0x00); //0 00000000 0x00 【0x04】System Registers, 【MCLK = XI/2】
// I2C_Read(0x01); //1 11001100 0xCC <0x8C> Input selection <32bit,i2s,auto,serial>
// I2C_Read(0x02); //2 00110100 0x34 Mixing, Serial Data and Automute Configuration
// I2C_Read(0x03); //3 01000000 0x40 SPDIF Configuration
// I2C_Read(0x04); //4 00000000 0x00 Automute Time
// I2C_Read(0x05); //5 01101000 0x68 Automute Level
// I2C_Read(0x06); //6 01000010 0x42 De-emphasis, DoP and Volume Ramp Rate
// I2C_Read(0x07); //7 10000000 0x80 Filter Bandwidth and System Mute
// I2C_Read(0x08); //8 11011101 0xDD GPIO1-2 Configuration
// I2C_Read(0x09); //9 00100010 0x22 Reserved
// I2C_Read(0x0A); //10 00000010 0x02 Master Mode and Sync Configuration
// I2C_Read(0x0B); //11 00000000 0x00 SPDIF Select
// I2C_Read(0x0C); //12 01011010 0x5A ASRC/DPLL Bandwidth
// I2C_Read(0x0D); //13 01000000 0x40 THD Bypass
// I2C_Read(0x0E); //14 00001010 0x0A 【0x42】Soft Start Configuration 【14号寄存器改成01000010】
// I2C_Read(0x0F); //15 01010000 0x50 【0x00】Volume Control1 【声音最大0db】
// I2C_Read(0x10); //16 01010000 0x50 【0x00】Volume Control2 【声音最大0db】
// I2C_Read(0x11); //17 11111111 0xFF Master Trim
// I2C_Read(0x12); //18 11111111 0xFF Master Trim
// I2C_Read(0x13); //19 11111111 0xFF Master Trim
// I2C_Read(0x14); //20 01111111 0x7F Master Trim
// I2C_Read(0x15); //21 00000000 0x00 GPIO Input Selection
// I2C_Read(0x16); //22 00000000 0x00 THD Compensation C2
// I2C_Read(0x17); //23 00000000 0x00 THD Compensation C2
// I2C_Read(0x18); //24 00000000 0x00 THD Compensation C3
// I2C_Read(0x19); //25 00000000 0x00 THD Compensation C3
// I2C_Read(0x1A); //26 01100010 0x62 Reserved
// I2C_Read(0x1B); //27 11010100 0xD4 General Configuration
// I2C_Read(0x1C); //28 11110000 0xF0 Reserved
// I2C_Read(0x1D); //29 00000000 0x00 GPIO configuration
// I2C_Read(0x1E); //30 00000000 0x00 Charge Pump Clock
// I2C_Read(0x1F); //31 00000000 0x00 Charge Pump Clock
// I2C_Read(0x20); //32 00000000 0x00 Reserved
// I2C_Read(0x21); //33 00111100 0x3C Interrupt Mask
// I2C_Read(0x22); //34 00000000 0x00 Programmable NCO
// I2C_Read(0x23); //35 00000000 0x00 Programmable NCO
// I2C_Read(0x24); //36 00000000 0x00 Programmable NCO
// I2C_Read(0x25); //37 00000000 0x00 Programmable NCO
// I2C_Read(0x26); //38 00000000 0x00 Reserved
// I2C_Read(0x27); //39 00000000 0x00 <0x20> General Configuration2 <reserved部分变更,无关紧要>
// I2C_Read(0x28); //40 00000000 0x00 Programmable FIR RAM Address
// I2C_Read(0x29); //41 00000000 0x00 Programmable FIR RAM Data
// I2C_Read(0x2A); //42 00000000 0x00 Programmable FIR RAM Data
// I2C_Read(0x2B); //43 00000000 0x00 Programmable FIR RAM Data
// I2C_Read(0x2C); //44 00000000 0x00 Programmable FIR Configuration
// I2C_Read(0x2D); //45 00000100 0x04 Low Power and Auto Calibration
// I2C_Read(0x2E); //46 00000000 0x00 ADC Configuration
// I2C_Read(0x2F); //47 11100000 0xE0 ADC Filter Configuration
// I2C_Read(0x30); //48 00000011 0x03 ADC Filter Configuration
// I2C_Read(0x31); //49 00000000 0x00 ADC Filter Configuration (fbq_scale)
// I2C_Read(0x32); //50 00001000 0x04 ADC Filter Configuration (fbq_scale)
// I2C_Read(0x33); //51 00000000 0x00 ADC Filter Configuration (fbq_scale)
// I2C_Read(0x34); //52 00001000 0x04 ADC Filter Configuration (fbq_scale)
// I2C_Read(0x35); //53 00011010 0x1A Reserved
// I2C_Read(0x36); //54 00001111 0x0F Reserved
// I2C_Read(0x40); //64 01110000 0x70 <0x72> (Read-Only)Chip ID and Status<没信号,静音被激活>
// I2C_Read(0x41); //65 00000000 0x00 (Read-Only)GPIO Readback
// I2C_Read(0x42); //66 00000000 0x00 (Read-Only)DPLL Number
// I2C_Read(0x46); //70 00000000 0x00 (Read-Only)SPDIF Channel Status/User Status
// I2C_Read(0x60); //96 00000000 0x00 <0x31> 【Ox04】(Read-Only)Input Selection and Automute Status 【SPDIF信号锁定】
// I2C_Read(0x64);//100 00000000 0x00 (Read-Only)ADC Readback
void main(void) //主程序这才开始,上面都是些定义
{
MCU_Init(); //stm8初始化
DAC_Init(); //解码芯片初始化
I2C_Write(0x00,0x04); //写解码芯片的0号寄存器,时钟用了100M的,频率太高耗电大,降频二分之一
I2C_Write(0x0E,0x42); //最关键的,参考坛子里老帖,另一个帖子设置是8a,反正我这里8a不行只有0x42出声
I2C_Write(0x0F,0x00); //写解码芯片的15号寄存器,音量最大0db
I2C_Write(0x10,0x00); //写解码芯片的16号寄存器,音量最大0db
while (1) //while循环语句,()内为真时循环,1是真所以无限循环
{
I2C_Read(0x60); //读取96号寄存器,SPDIF状态
if(SPDIF_STATUS==0x04) //如果,SPDIF锁定了信号。C语言里面一个等号是赋值,两个等号是是否等于的判断(注意这里没有分号)
GPIO_WriteLow(GPIOD, (GPIO_Pin_TypeDef)GPIO_PIN_3); //那么,PD3脚输出低电平,LED亮
else
GPIO_WriteHigh(GPIOD, (GPIO_Pin_TypeDef)GPIO_PIN_3); //否则,PD3脚输出高电平,LED灭
Delay(0xFFFF); //隔0.5秒循环一次读取96号寄存器
Delay(0xFFFF);
Delay(0xFFFF);
Delay(0xFFFF);
Delay(0xFFFF);
}
}
#ifdef USE_FULL_ASSERT //这个是标准程序不用管它,调试时返回值验证出错的时候调用
void assert_failed(uint8_t* file, uint32_t line)
{
while (1)
{
}
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3. 程序调试及烧录
以上代码写完之后点“save all”, 然后点“Make”,下面会有提示和报错,都没有就OK了。没报错时会在项目的debug\exe文件夹里生成.hex文件,这个文件可以用于stvp等普通烧录工具直接写到芯片里,但咱用不上。
接着需要连接st link和stm8s103芯片都连接好,然后点击“download and debug”,这时IAR会将程序直接写入芯片,并进入在线调试模式。
另外截图左面可以看到哪些库文件添加到了work space里面了。
做完上一步,点菜单上的view,把窗口live watch打开,然后在这里添加两个需要观察的变量:我程序一开始定义的全局变量R和SPDIF_STATUS。然后点击“next statement”,开始一步一步执行程序,变量的值会直接显示在live watch窗口里。
调试结束后点红色的”X“推出调试。
到此,写程序和调试烧录程序都完成了,直接拔掉线,解码板就可以正常运行了。
对了,还有一个新手可能看不懂的,ES9038Q2M的数据手册里的寄存器描述~ 这东西自己琢磨好久~如下说明:
最上面0就是第0个寄存器,写成16进制就是0x00,这是寄存器地址。
[7:4] 这些是代表8位2进制的前4位,每4位2进制就是1位16进制,所以[7:4]就是两位16进制数的前一位。
4‘b0000这个,b代表2进制,d代表10进制,是具体寄存器前4位的值,默认四个0。
2进制、10进制、16进制的转换可以用windows计算器,设置成程序员模式。
先写这些,也许有些人会不开心,,, 但我来hifidiy这么久,一直没能发点有价值的,耿耿于怀~自认为分享了点有用的,很是开心~~哈哈
补充内容 (2023-12-31 21:38):
上面代码的I2C_Read定义中下面这一行请删掉,否则连续读取多次时I2C会卡死。
while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED)); //等待EV7,接收完成
补充内容 (2024-9-2 13:18):
更上一步,请看下面帖子:
http://bbs.hifidiy.net/forum.php ... =1504899&extra= |
评分
-
查看全部评分
|