S3C6410裸机AC97驱动

目前能够初始化AC97,能够进入就绪中断,说明能够检测到WM9714,但是无法读取WM9714,不知道哪里出错了,目前正在解决中...

AC97.c

/*************************************************************************************************************
 * 文件名: AC97.c
 * 功能:  S3C6410 AC97底层驱动函数
 * 作者:  cp1300@139.com
 * 创建时间: 2012年10月6日20:41
 * 最后修改时间:2012年10月6日
 * 详细:  AC97控制器底层驱动
*************************************************************************************************************/
#include "system.h"
#include "ac97.h"
#include "delay.h"


//使能AC97-LINK传输数据
#define AC97_EnTraansferACLink()  (AC97->GLBCTRL |= BIT3) 
//使能AC97-LINK
#define AC97_ACLinkOn()    (AC97->GLBCTRL |= BIT2) 


//AC97中断定义
#define AC97_ALL_INT  (0x7f << 16)//全部中断
#define CODE_READY_INT  (1 << 22) //编解码器准备就绪中断
#define PCM_OUT_UNDER_INT (1 << 21) //PCM输出通道FIFO空中断
#define PCM_IN_OVER_INT  (1 << 20) //PCM输入通道FIFO满中断
#define MIC_IN_OVER_INT  (1 << 19) //MIC输入通道FIFO满中断
#define PCM_OUT_THRES_INT (1 << 18) //PCM输出通道FIFO半满中断
#define PCM_IN_THRES_INT (1 << 17) //PCM输入通道FIFO半满中断
#define MIC_IN_THRES_INT (1 << 16) //MIC输入通道FIFO半满中断


//延时控制,单位US
#define AC97_WARMRESET_DELAY  2 //系统热复位延时
#define AC97_COLDRESET_DELAY  2 //系统冷复位延时
#define AC97_CMDREAD_DELAY   2000//读取延时
#define AC97_CMDWRITE_DELAY   22 //写命令延时


/*************************************************************************************************************************
*函数    : void AC97_WarmReset(void)
*功能    : AC97控制器热复位
*参数    : 无
*返回    : 无
*依赖 :  底层宏定义
*作者    : cp1300@139.com
*时间    : 20121006
*最后修改时间: 20121006
*说明    : 用于从关闭电源唤醒编解码器
*************************************************************************************************************************/
void AC97_WarmReset(void)
{
 AC97->GLBCTRL &= ~(0xf);   //清除设置
 AC97->GLBCTRL |= BIT1;    //开始复位
 Delay_US(AC97_WARMRESET_DELAY);  //延时,大于1US
 AC97->GLBCTRL &= ~BIT1;    //结束复位
 AC97_ACLinkOn();
 AC97_EnTraansferACLink();
 Delay_US(1);
}


/*************************************************************************************************************************
*函数    : void AC97_ColdReset(void)
*功能    : AC97控制器冷复位
*参数    : 无
*返回    : 无
*依赖 :  底层宏定义
*作者    : cp1300@139.com
*时间    : 20121006
*最后修改时间: 20121006
*说明    : 用于复位编解码器和控制器的逻辑,复位时间最小1us
*************************************************************************************************************************/
void AC97_ColdReset(void)
{
 AC97->GLBCTRL |= BIT0;    //开始复位
 Delay_US(AC97_COLDRESET_DELAY);
 AC97->GLBCTRL &= ~BIT0;    //结束复位
 AC97_WarmReset();
 Delay_US(1);
}


/*************************************************************************************************************************
*函数    : u8 AC97_Init(void)
*功能    : AC97控制器初始化
*参数    : 无
*返回    : 1:初始化失败;0:初始化成功
*依赖 :  底层宏定义
*作者    : cp1300@139.com
*时间    : 20121006
*最后修改时间: 20121006
*说明    : 无
*************************************************************************************************************************/
u8 AC97_Init(void)
{
 u16 i = 0;
 
 //初始化AC97硬件接口
 rGPDPUD = 0x1 << 2; //AC97BITCLK CDCLK Pull Down Enable
 rGPDCON = 0x44444;
 Set_GateClk(PCLK_AC97,ENABLE);  //使能AC97控制器门控时钟
 AC97_ColdReset();     //AC97控制器冷复位
 AC97_IntClear(CODE_READY_INT);     //清除准备就绪中断
 AC97_IntEnable(CODE_READY_INT,ENABLE);   //使能准备就绪中断
 while(!(AC97_GetIntStatus() & CODE_READY_INT)) //等待准备就绪中断
 {
  i ++;
  if(i > 1000)
  {
   DEBUG("AC97 Waint Time Out!\n");
   return 1;
  }
  Delay_MS(1);
 }
 AC97_IntEnable(CODE_READY_INT,DISABLE);   //关闭准备就绪中断
 AC97_IntClear(CODE_READY_INT);     //清除准备就绪中断
 Delay_MS(1);
 
 return 0;
}


/*************************************************************************************************************************
*函数    : u16 AC97_CodeCMD(AC97_CMD AC97_RW,u8 RegAddr,u16 CmdData)
*功能    : AC97读写命令控制
*参数    : AC97_RW:读写控制,见AC97_CMD;RegAddr:寄存器地址;CmdData:命令数据
*返回    : 无
*依赖 :  底层宏定义
*作者    : cp1300@139.com
*时间    : 20121006
*最后修改时间: 20121006
*说明    : 连续写命令需要延时,一个命令到下一个命令之间有延时多于1 / 48KHz 大约23US
*************************************************************************************************************************/
u16 AC97_CodeCMD(AC97_CMD AC97_RW,u8 RegAddr,u16 CmdData)
{
 if(AC97_RW == AC97_READ) //读取
 {
  AC97->CODEC_CMD = (u32)((RegAddr << 16) | (1 << 23) | (0 << 0));
  Delay_US(AC97_CMDREAD_DELAY);
  return (u16)(AC97->CODEC_STAT & 0xffff);
 }
 else if(AC97_RW == AC97_WRITE) //写入
 {
  AC97->CODEC_CMD = (u32)((RegAddr << 16) | (0 << 23) | (CmdData << 0));
  Delay_US(AC97_CMDWRITE_DELAY);
  return 0;
 }
 else
 {
  DEBUG("AC97 CMD Error!\n");
  return 0;
 }
}


/*************************************************************************************************************************
*函数    :  void AC97_IntEnable(u32 Int,u8 Enable)
*功能    :  AC97控制器中断控制
*参数    :  Int:中断编号,见宏定义;Enable:ENABLE:使能中断,DISABLE:取消中断
*返回    :  无
*依赖 :  底层宏定义
*作者    :  cp1300@139.com
*时间    : 20121008
*最后修改时间: 20121008
*说明    : 无
*************************************************************************************************************************/
void AC97_IntEnable(u32 Int,u8 Enable)
{
 if(Enable == ENABLE) //使能中断
 {
  AC97->GLBCTRL |= Int;
 }
 else     //取消中断
 {
  AC97->GLBCTRL &= ~Int;
 }
}


/*************************************************************************************************************************
*函数    :  void AC97_IntClear(u32 Int)
*功能    :  AC97控制器中断清除
*参数    :  Int:中断编号,见宏定义
*返回    :  无
*依赖 :  底层宏定义
*作者    :  cp1300@139.com
*时间    : 20121008
*最后修改时间: 20121008
*说明    : 无
*************************************************************************************************************************/
void AC97_IntClear(u32 Int)
{
 AC97->GLBCTRL |= (Int << 8); //写1清除对应中断
}

/*************************************************************************************************************************
*函数    :  u32 AC97_GetIntStatus(void)
*功能    :  获取AC97中断状态
*参数    :  无
*返回    :  中断状态
*依赖 :  底层宏定义
*作者    :  cp1300@139.com
*时间    : 20121008
*最后修改时间: 20121008
*说明    : 返回的中断状态与中断编号相与
*************************************************************************************************************************/
u32 AC97_GetIntStatus(void)
{
 return (AC97->GLBSTAT & (0x7f << 16));
}

/*************************************************************************************************************************
*函数    :  AC97_State AC97_GetContStatus(void)
*功能    :  获取AC97控制器状态
*参数    :  无
*返回    :  控制器状态,见AC97_State
*依赖 :  底层宏定义
*作者    :  cp1300@139.com
*时间    : 20121009
*最后修改时间: 20121009
*说明    : 无
*************************************************************************************************************************/
AC97_State AC97_GetContStatus(void)
{
 return (AC97_State)(AC97->GLBSTAT & 0x07);
}


//AC97控制器中断服务程序
void __irq Isr_AC97(void)
{
 if(AC97->GLBSTAT & CODE_READY_INT)  //编解码器准备就绪中断
 {
 
 }
 if(AC97->GLBSTAT & PCM_OUT_UNDER_INT) //PCM输出通道FIFO空中断
 {
 
 }
 if(AC97->GLBSTAT & PCM_IN_OVER_INT)  //PCM输入通道FIFO满中断
 {
 
 }
 if(AC97->GLBSTAT & MIC_IN_OVER_INT)  //MIC输入通道FIFO满中断
 {
 
 }
 if(AC97->GLBSTAT & PCM_OUT_THRES_INT) //PCM输出通道FIFO半满中断
 {
 
 }
 if(AC97->GLBSTAT & PCM_IN_THRES_INT) //PCM输入通道FIFO半满中断
 {
 
 }
 if(AC97->GLBSTAT & MIC_IN_THRES_INT)  //MIC输入通道FIFO半满中断
 {
 
 }
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/afd2f8d27f448807d59027c1918f17eb.html