S3C6410裸机AC97驱动

来源:互联网 发布:java encodeuri 解码 编辑:程序博客网 时间:2024/05/21 07:54

目前能够初始化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_DELAY2//系统热复位延时#define AC97_COLDRESET_DELAY2//系统冷复位延时#define AC97_CMDREAD_DELAY2000//读取延时#define AC97_CMDWRITE_DELAY22//写命令延时/**************************************************************************************************************************函数    :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);//延时,大于1USAC97->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 EnablerGPDCON = 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中断服务程序中闪烁,周期400MSvoid LED1_flash(void){LED1_FLASH();}int main(void){LCD_Init();//初始化LCDUART0_Init(DISABLE,115200);//初始化串口,失能中断接收,波特率115200LED_Init();//初始化LEDTimer1_Init(400000-1,ENABLE,LED1_flash);//初始化定时器0,周期400mslcd_printf("Get_FCLK : %d Hz\n",Get_FCLK());lcd_printf("Get_PCLK : %d Hz\n",Get_PCLK());if(AC97_Init())//初始化AC97控制器{lcd_printf("AC97 Init error!\n");}else{lcd_printf("AC97 Init OK!\n");}lcd_printf("0x%X\n",AC97_CodeCMD(AC97_READ,0x7c,0));lcd_printf("0x%X\n",AC97_CodeCMD(AC97_READ,0x7e,0));while(1){LED2_FLASH();//LED2闪烁Delay_US(600000);}}



我读取这两个寄存器的值,但是读取到的一直是0,不知道问题在哪,明天继续解决


//寄存器映射

//AC97控制器 寄存器typedef struct{vu32GLBCTRL;  // 0x7F001000 读/写 AC97 通用控制寄存器。 0x00000000vu32GLBSTAT;  // 0x7F001004 读 AC97 全球状态寄存器。 0x00000001vu32CODEC_CMD;  // 0x7F001008 读/写 AC97 编解码器命令寄存器。 0x00000000vu32CODEC_STAT;  // 0x7F00100C 读AC97 编解码器状态寄存器。 0x00000000vu32PCMADDR;  // 0x7F001010 读 AC97 的PCM 输出/输入 通道FIFO 地址0x00000000vu32MICADDR;  // 0x7F001014 读 AC97 的MIC 输入通道FIFO 地址寄存器。0x00000000vu32PCMDATA;  // 0x7F001018 读/写 AC97 的PCM 输出/输入 通道FIFO 数据0x00000000vu32MICDATA;  // 0x7F00101C 读/写 AC97 的MIC 输入通道FIFO 数据寄存器。 0x00000000}AC97_TypeDef;

//AC97 控制器#define AC97_BASE0x7F001000

#define AC97((AC97_TypeDef*)AC97_BASE)