⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codec.c

📁 dspic开发控制程序,有助开发pic单片机程序
💻 C
字号:
#include <p30f6014.h>
#include <dci.h>
#include "common.h"
#include "timers.h"
#include "codec.h"

#define FRAMECLKRATE  (SAMPLE_RATE*256L)

#define CMD_STAGE0 0	//正常模式
#define CMD_STAGE1 1	//设置lsb告诉解码器下一个控制字是命令
#define CMD_STAGE2 2	//把带命令的字节放到输出缓冲
#define CMD_STAGE3 3	//设置帧模式
#define CMD_STAGE4 4	//回复正常帧模式

#define QUEUE_SIZE (PROC_BLOCK_SIZE*2)	//Rx和Tx队列的大小,必须为处理缓冲
																				//大小的2倍

unsigned int* pActiveRxBuf;
unsigned int* pActiveTxBuf;

static volatile unsigned char CmdStage;
static volatile unsigned int CodecCmd;
static volatile char ClkAdjTrig;

static int TxQue[QUEUE_SIZE];
static int RxQue[QUEUE_SIZE];
static volatile unsigned int TxQTail;
static volatile unsigned int RxQHead;


void InitCodec(void);
void WriteCodecCtrl( unsigned char adr, unsigned char parm );
void AdjustClock( char shift );
unsigned char ReadCodecCtrl( unsigned char adr );

//把数据放到接收缓冲的子程序
inline void PutRxQue(int data)
{
	RxQue[RxQHead++] = data;
	if(RxQHead==QUEUE_SIZE)	
	{
		RxQHead = 0;	
		pActiveRxBuf = RxQue + QUEUE_SIZE/2;	
		SemA.CodecRxDataRdy = TRUE;
	}
	else
	{
		if(RxQHead==QUEUE_SIZE/2)
		{
			pActiveRxBuf = RxQue;	
			SemA.CodecRxDataRdy = TRUE;
		}
	}
}

//从接收缓冲获取数据的子程序
inline int GetTxQue(void)
{
static int tmp;		//因为是在线(inline)函数,须定义为静态
	tmp = TxQue[TxQTail++]&0xFFFE;
	if(TxQTail==QUEUE_SIZE)
	{
		TxQTail = 0;	
		pActiveTxBuf = TxQue+QUEUE_SIZE/2;
		SemA.CodecTxDataRdy = TRUE;
	}
	else
	{
		if(TxQTail==QUEUE_SIZE/2)
		{
			pActiveTxBuf = TxQue;
			SemA.CodecTxDataRdy = TRUE;
		}
	}
	return tmp;
}

//DCI中断服务子程序
void __attribute__((__interrupt__)) _DCIInterrupt(void)
{
int tmp;
	switch(	CmdStage )
	{
		case CMD_STAGE0:
			TXBUF0 = GetTxQue();
 			TXBUF1 = GetTxQue();
			TXBUF2 = GetTxQue();
			TXBUF3 = GetTxQue();
			PutRxQue(RXBUF0);
			PutRxQue(RXBUF1);
			PutRxQue(RXBUF2);
			tmp = RXBUF3;			    //调整时钟的相位
			if(ClkAdjTrig > 0)		//如果需要插入采样
				PutRxQue(tmp);
			if(ClkAdjTrig >= 0)		//如果不须,则跳过
				PutRxQue(tmp);
			ClkAdjTrig = 0;
			break;
		case CMD_STAGE1:
			TXBUF0 = GetTxQue();
			TXBUF1 = GetTxQue();
			TXBUF2 = GetTxQue();
			TXBUF3 = GetTxQue() | 1;	//告诉编码解码器下一个值是命令
			PutRxQue(RXBUF0);
			PutRxQue(RXBUF1);
			PutRxQue(RXBUF2);
			PutRxQue(RXBUF3);
			CmdStage = CMD_STAGE2;
			break;
		case CMD_STAGE2:
			TXBUF0 = CodecCmd;  	//插入编码解码器命令
			TXBUF1 = GetTxQue();	//取采样数据
			TXBUF2 = 0x0000;		  //写虚拟值
			TXBUF3 = 0x0000;		  //写虚拟值
			PutRxQue(RXBUF0);
			PutRxQue(RXBUF1);
			PutRxQue(RXBUF2);
			PutRxQue(RXBUF3);
			CmdStage = CMD_STAGE3;
			break;
		case CMD_STAGE3:
			TXBUF0 = GetTxQue();
			TXBUF1 = GetTxQue();
			TXBUF2 = GetTxQue();
			TXBUF3 = GetTxQue();
			PutRxQue(RXBUF0);
			PutRxQue(RXBUF1);
			PutRxQue(RXBUF2);
			PutRxQue(RXBUF3);
			//设置DCI缓冲长度为2
			DCICON2 = DCI_BUFF_LEN_2 & DCI_FRAME_LEN_8 & DCI_DATA_WORD_16;
			CmdStage = CMD_STAGE4;
			break;
		case CMD_STAGE4:
			TXBUF0 = GetTxQue();
			TXBUF1 = GetTxQue();
			TXBUF2 = GetTxQue();
			TXBUF3 = GetTxQue();
			CodecCmd = RXBUF0;
			PutRxQue(RXBUF1);
			//设置DCI缓冲长度为4
			DCICON2 = DCI_BUFF_LEN_4 & DCI_FRAME_LEN_16 & DCI_DATA_WORD_16;
			CmdStage = CMD_STAGE0;
			break;
	}
	IFS2bits.DCIIF = 0; // 清DCI中断标志
}

//初始化DCI和编码解码器
void InitCodec(void)
{
int i;
	for(i=0; i<QUEUE_SIZE ;i++)
	{
		RxQue[i] = 0;
		TxQue[i] = 0;
	}
	TxQTail = 0;
	RxQHead = 0;
	SemA.CodecRxDataRdy = FALSE;
	SemA.CodecTxDataRdy = FALSE;
	CmdStage = CMD_STAGE0;
	CodecCmd = 0;
	ClkAdjTrig = 0;
	TRISFbits.TRISF6 = 1;	//编码解码器(Codec)引脚为输入
	/* 配置DCI接收/传送中断*/
	ConfigIntDCI( DCI_INT_ON & DCI_INT_PRI_6);
	/* 配置DCI模块用于传送16位数据且工作在多通道模式*/
	/*详细的位定义请参见文件 dci.h */
	OpenDCI(	DCI_EN & DCI_IDLE_CON &
					DCI_DIGI_LPBACK_DIS &
					DCI_SCKD_OUP &
					DCI_FSD_OUP &
					DCI_SAMP_CLK_FAL &
					DCI_TX_ZERO_UNF &
					DCI_SDO_TRISTAT &
//					DCI_SDO_ZERO &
					DCI_DJST_OFF &
					DCI_FSM_MULTI,
				DCI_BUFF_LEN_4 & DCI_FRAME_LEN_16 & DCI_DATA_WORD_16,
				( CLOCK_FREQ / ( 2 * FRAMECLKRATE) ) - 1,
				~DCI_DIS_SLOT_0,
				~DCI_DIS_SLOT_0
			);
	LATFbits.LATF6 = 0;	//复位编码解码器
	TRISFbits.TRISF6 = 0;
	TimeDelay(1);
	TRISFbits.TRISF6 = 1;	//编码解码器设为输入
	TimeDelay(1);
	//发送编码解码器的设定参数
	WriteCodecCtrl( CODEC_N1, 1-1);		//N=1
	WriteCodecCtrl( CODEC_M1, 20-1);	//M=20
	WriteCodecCtrl( CODEC_CTRL_1,CODEC_PARM_LPD|CODEC_PARM_SPD );
	WriteCodecCtrl( CODEC_CTRL_2, 0);	//Div除以5, HPF使能
	WriteCodecCtrl( CODEC_RXGAIN, CODEC_PARM_HIM|CODEC_PARM_MCG0|CODEC_PARM_LIG0); 
	WriteCodecCtrl( CODEC_ADCVOL, CODEC_PARM_LOM| (23<<2) ); 
	WriteCodecCtrl( CODEC_DACVOL, CODEC_PARM_SLM|CODEC_PARM_SRM|(23<<2) ); 
	WriteCodecCtrl( CODEC_ATTN, CODEC_PARM_SOT0|CODEC_PARM_LOT0); 
}

//写命令到编码解码器子程序
void WriteCodecCtrl( unsigned char adr, unsigned char parm )
{
	CodecCmd = (unsigned int)adr;
	CodecCmd = (CodecCmd<<8) & 0x1F00;
	CodecCmd += (unsigned int)parm;
	CmdStage = CMD_STAGE1;
	while( CmdStage != CMD_STAGE0 ){}	
}

//从编码解码器读命令子程序
unsigned char ReadCodecCtrl( unsigned char adr )
{
	CodecCmd = (unsigned int)adr;
	CodecCmd = (CodecCmd<<8) & 0x1F00;
	CodecCmd |=  0x2000;
	CmdStage = CMD_STAGE1;
	while( CmdStage != CMD_STAGE0 ){}	
	return CodecCmd&0x00FF;
}

//调整时钟子程序
void AdjustClock( char shift )
{
	ClkAdjTrig = shift;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -