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半满中断 { } }
AC97.h
/************************************************************************************************************* * 文件名: AC97.h * 功能: S3C6410 AC97底层驱动函数 * 作者: cp1300@139.com * 创建时间: 2012年10月6日20:41 * 最后修改时间:2012年10月6日 * 详细: AC97控制器底层驱动 *************************************************************************************************************/ #ifndef AC97_H_ #define AC97_H_ //AC97控制器状态 typedef enum { AC97_State_Idle = 0, AC97_State_Init = 1, AC97_State_Ready = 2, AC97_State_Active = 3, AC97_State_LP = 4, AC97_State_Warm = 5 }AC97_State; //AC97读写命令控制 typedef enum { AC97_WRITE = 0, AC97_READ = 1 }AC97_CMD; u8 AC97_Init(void); //AC97初始化 u16 AC97_CodeCMD(AC97_CMD AC97_RW,u8 RegAddr,u16 CmdData); void AC97_IntEnable(u32 Int,u8 Enable); void AC97_IntClear(u32 Int); u32 AC97_GetIntStatus(void); AC97_State AC97_GetContStatus(void); #endif /*AC97_H_*/
//main.c
#include "system.h" #include "uart.h" #include "tft_lcd.h" #include "other.h" #include "delay.h" #include "timer.h" #include "ac97.h" //LED1闪烁程序,在定时器0中断服务程序中闪烁,周期400MS void LED1_flash(void) { LED1_FLASH(); } int main(void) { LCD_Init(); //初始化LCD UART0_Init(DISABLE,115200); //初始化串口,失能中断接收,波特率115200 LED_Init(); //初始化LED Timer1_Init(400000-1,ENABLE,LED1_flash); //初始化定时器0,周期400ms lcd_printf("Get_FCLK : %d Hzn",Get_FCLK()); lcd_printf("Get_PCLK : %d Hzn",Get_PCLK()); if(AC97_Init()) //初始化AC97控制器 { lcd_printf("AC97 Init error!n"); } else { lcd_printf("AC97 Init OK!n"); } lcd_printf("0x%Xn",AC97_CodeCMD(AC97_READ,0x7c,0)); lcd_printf("0x%Xn",AC97_CodeCMD(AC97_READ,0x7e,0)); while(1) { LED2_FLASH(); //LED2闪烁 Delay_US(600000); } }
我读取这两个寄存器的值,但是读取到的一直是0,不知道问题在哪,明天继续解决
//寄存器映射
//AC97控制器 寄存器 typedef struct { vu32 GLBCTRL; // 0x7F001000 读/写 AC97 通用控制寄存器。 0x00000000 vu32 GLBSTAT; // 0x7F001004 读 AC97 全球状态寄存器。 0x00000001 vu32 CODEC_CMD; // 0x7F001008 读/写 AC97 编解码器命令寄存器。 0x00000000 vu32 CODEC_STAT; // 0x7F00100C 读 AC97 编解码器状态寄存器。 0x00000000 vu32 PCMADDR; // 0x7F001010 读 AC97 的PCM 输出/输入 通道FIFO 地址 0x00000000 vu32 MICADDR; // 0x7F001014 读 AC97 的MIC 输入通道FIFO 地址寄存器。 0x00000000 vu32 PCMDATA; // 0x7F001018 读/写 AC97 的PCM 输出/输入 通道FIFO 数据 0x00000000 vu32 MICDATA; // 0x7F00101C 读/写 AC97 的MIC 输入通道FIFO 数据寄存器。 0x00000000 }AC97_TypeDef;
//AC97 控制器 #define AC97_BASE 0x7F001000
#define AC97 ((AC97_TypeDef*)AC97_BASE)