TM8211是两路16位数模转换集成电路,可广泛应用于数字音频、多媒体系统。 芯片采用CMOS工艺设计,内部电路结构基于R-2R电阻网络结构设计,并在全电源 电压范围内实现16bit的动态范围。 TM8211可通过采用数字串行总线数据输入,采 用快速R-2R网络结构来支持8X的过采样音频信号处理。 TM8211 支持较宽范围的采样频率,并与PT8211、TDA1311兼容,输入采用 LSBJ (Least Significant Bit Justified ) 格式, 数字编码格式采用MSB在前的补码格 式。
具体关于tm8211的介绍这里不再赘述,详见数据手册,这里主要讲解tm8211的驱动方式
tm8211的靠三个引脚对双通道输出进行配置:
WS: 高电平指示对LCH通道进行配置,低电平指示对RCH通道进行配置;
BCK:配置过程的时钟线,TM8211在时钟上升沿锁存数据,在WS的某个电平状态,前16个时钟锁存的数据有效,后面的忽略;
DIN: 配置过程的数据线,高电平为1,低电平为0;
有一个很容易忽略而又重要的问题就是tm8211处理的是int16_t的整数,而在编写keil时容易习惯写成无符号16位整型uint16_t,导致超范围而使输出值错误并且不稳定。
此外,tm8211输出的是1/4vcc~3/4vcc,因此vcc最好使用高精度电压基准提供,并做好滤波。
本例程用于作普通高精度dac使用,不用于音频输出;
下面delay时间为大约0.5us,即2M左右工作频率,想改动的改time即可(一般不用改动,而且驱动tm8211作普通16位dac对时钟精度要求不高,直接while(time--)即可,没必要用delay函数)
用stm32来驱动tm8211的代码如下:
/*tm8211.c*/
#include "tm8211.h"
/*在此处更改引脚*/
#define TM8211_WS_L HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET)
#define TM8211_WS_H HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET)
#define TM8211_BCK_L HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET)
#define TM8211_BCK_H HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET)
#define TM8211_DIN_L HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET)
#define TM8211_DIN_H HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET)
/**
* @brief 引脚配置
* @param 无
* @retval 无
*/
void TM8211_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
/*Configure GPIO pins : PA1 PA2 PA3 */
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/**
* @brief tm8211左右通道设置
* @param lch rch 数字量,范围:-32768~32767
* @retval 无
*/
void tm8211_set(int16_t lch, int16_t rch)
{
uint8_t i,time=5;
/*配置右通道*/
TM8211_WS_L;
while(time--);
for(i=0; i<16; i++)
{
TM8211_BCK_L;
if( (rch>>(15-i))&0x0001 ) TM8211_DIN_H;
else TM8211_DIN_L;
while(time--);
TM8211_BCK_H;
while(time--);
}
while(time--);
/*配置左通道*/
TM8211_WS_H;
while(time--);
for(i=0; i<16; i++)
{
TM8211_BCK_L;
if( (lch>>(15-i))&0x0001 ) TM8211_DIN_H;
else TM8211_DIN_L;
while(time--);
TM8211_BCK_H;
while(time--);
}
while(time--);
TM8211_WS_L;
}
/*tm8211.h*/
#ifndef __TM8211_H
#define __TM8211_H
#include "main.h"
void TM8211_GPIO_Init(void);
void tm8211_set(int16_t lch, int16_t rch);
#endif