2015年长江大学电子设计竞赛
基于MSP430F5529的MP3设计
2015年5月6日
摘 要
本系统主要由MSP430F5529单片机和VS1003音频解码芯片组成,MCU通过SPI串行协议读取SD卡的音频文件,将音频文件发送给VS1003音频解码,解码后的音频信号经功率放大器放大后驱动电声转换器件发出声响,系统另外配备有由键盘和LCD组成的人机交互功能,整个系统简洁、功能完善。
。
I
目 录
1系统方案 ........................................................................................................................................ 1
1.1主控的论证与选择 ............................................................................................................. 1 1.2 音频解码的论证与选择 .................................................................................................... 1 1.3 控制系统的论证与选择 .................................................................... 错误!未定义书签。 2系统理论分析与计算 .................................................................................................................... 1
2.1 XXXX的分析 ................................................................................. 错误!未定义书签。
2.1.1 XXX ......................................................................................... 错误!未定义书签。 2.1.2 XXX ......................................................................................... 错误!未定义书签。 2.1.3 XXX ......................................................................................... 错误!未定义书签。 2.2 XXXX的计算 .................................................................................... 错误!未定义书签。
2.2.1 XXX ......................................................................................... 错误!未定义书签。 2.2.2 XXX ......................................................................................... 错误!未定义书签。 2.2.3 XXX ......................................................................................... 错误!未定义书签。 2.3 XXXX的计算 .................................................................................... 错误!未定义书签。
2.3.1 XXX ......................................................................................... 错误!未定义书签。 2.3.2 XXX ......................................................................................... 错误!未定义书签。 2.3.3 XXX ......................................................................................... 错误!未定义书签。
3电路与程序设计 ............................................................................................................................ 1
3.1电路的设计 ......................................................................................................................... 1
3.1.1系统总体框图 .......................................................................................................... 1 3.1.2 SD卡子系统框图与电路原理图 ............................................................................ 2 3.1.3音频放大子系统框图与电路原理图 ...................................................................... 2 3.1.4电源 .......................................................................................................................... 3 3.2程序的设计 ......................................................................................................................... 3
3.2.1程序功能描述与设计思路 ...................................................................................... 3 3.2.2程序流程图 .............................................................................................................. 3
4测试方案与测试结果 .................................................................................................................... 3
4.1测试方案 ............................................................................................................................. 3 4.2 测试条件与仪器 ................................................................................ 错误!未定义书签。 4.3 测试结果及分析 ................................................................................................................ 4
4.3.1测试结果(数据) ....................................................................... 错误!未定义书签。 4.3.2测试分析与结论 ...................................................................................................... 4
附录1:电路原理图 ........................................................................................................................ 5 附录2:源程序 ................................................................................................................................ 6
II
基于MSP430F5529的MP3
【熊平波组】
1系统方案
本系统主要由MSP430F5529模块、VS1003模块、SD卡模块、电源模块组成,下面分别论证这几个模块的选择。
1.1 主控芯片的论证与选择
方案一:51单片机。
51单片机出现年代较早,所以各种资料也非常的多,实现起来比较简单,达不
到学习锻炼的目的,所以只以他作为一个参考。 方案二:STM32单片机
STM32单片机虽然是近几年推出的单片机,但它以强大的性能,低廉的价格很快的占领了市场,目前这方面的资料也是非常的多,并且个人对这一型号的处理器不是很了解,所以也放弃选用。 方案三:MSP430单片机
MSP430是TI公司现在主推的单片机型号,也是历年电子设计大赛所大量选用的处理器型号,它具有极低功耗,超强模拟外设。
综合以上三种方案,选择方案三。
1.2音频解码的论证与选择
方案一:AD+滤波器 。
由单片机直接将SD卡里面WAV格式的音频文件传送到AD转换器,进行音频输出,优点是操作简单,成本低,缺点是音质较差 方案二:VS1003音频解码芯片。
VS1003是由芬兰 VLSI 公司出品的一款单芯片的MP3/WMA音频解码芯片,其 拥有一个高性能低功耗的 DSP 处理器核VS_DSP,5K的指令 RAM,0.5K的数据 RAM,串行的控制和数据输入接口,4 个通用 IO 口,一个 UART 口,同时片内带有一个 可变采样率的 ADC、一个立体声 DAC 以及音频耳机放大器。性能优良,操作简单
综合以上二种方案,选择方案二。
2系统理论分析与计算
3电路与程序设计
3.1电路的设计
3.1.1系统总体框图
系统总体框图如图1所示
1
Nokia511 液晶 SD卡 MSP430F5529 键盘+红外
VS1003 音频放大 图1 系统总体框图
3.1.2 SD卡子系统电路原理图
2、SD卡子系统电路
图2 SD卡子系统电路
3.1.3 音频放大子系统框图与电路原理图
2、音频放大子系统电路
2
图3 音频放大子系统电路
3.1.4电源
电源由变压部分、滤波部分、稳压部分组成。为整个系统提供
5V或者
12V电
压,确保电路的正常稳定工作。这部分电路比较简单,都采用三端稳压管实现,故不作详述。
3.2程序的设计
3.2.1程序功能描述与设计思路
1、程序功能描述
根据题目要求软件部分主要实现键盘的设置和显示。 1)键盘实现功能:设置音量、对比度、选歌。
2)显示部分:歌曲、演唱者、频谱、码率、时长、音量。 2、程序设计思路
3.2.2程序流程图
1、主程序流程图
4测试方案与测试结果
4.1测试方案
1、硬件测试
2、软件仿真测试
3
3、硬件软件联调
4.3 测试结果及分析
4.3.2测试分析与结论
根据上述测试数据,XXXXXXXXXXXXXXXXXXXXXXXXXXXXX,由此可以得出以下结论:
1、 2、 3、
综上所述,本设计达到设计要求。
4
附录1:实物图
5
附录2:源程序
/*
* LCD5110.h *
* Created on: 2014-11-22 * Author: xiongpb */
#ifndef LCD5110_H_ #define LCD5110_H_
#include #define uchar unsigned char #define uint unsigned int //延时宏定义 #define CPU_F ((double)4000000) #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0)) //枚举 D/C模式选择 typedef enum //emum为枚举常量 { DC_CMD = 0, //写命令 DC_DATA = 1 //写数据 } DCType; #define LCD_CLK_L P2OUT &= ~BIT2 //低电平 #define LCD_CLK_H P2OUT |=BIT2 //高电平 //数据输入端口 #define LCD_DIN_L P7OUT &= ~BIT4 //低电平 #define LCD_DIN_H P7OUT |=BIT4 //高电平 //数据/命令选择 #define LCD_DC_L P8OUT &= ~BIT1 //低电平 #define LCD_DC_H P8OUT |=BIT1 //高电平 //芯片使能 #define LCD_CE_L P4OUT &= ~BIT3 //低电平 #define LCD_CE_H P4OUT |=BIT3 //高电平 6 //串行输入复位 #define LCD_RST_L P4OUT &= ~BIT0 //低电平 #define LCD_RST_H P4OUT |=BIT0 //高电平 void LCD_write_byte(unsigned char data, DCType dc); void LCD5110_Init(void); void LCD5110_SetContrast(unsigned char contrast); void LCD5110_Clear(void); void LCD_Set_XY(unsigned char X, unsigned char Y); void LCD_WriteChar(unsigned char x,unsigned char y,unsigned char c); void LCD_WriteString(unsigned char X,unsigned char Y,char *s); void LCD_WriteNum(unsigned char X,unsigned char Y,unsigned int num); void LCD_Write_12X16Font(unsigned char x,unsigned char y,unsigned char *c); void LCD_DrawPicture(unsigned char X,unsigned char Y,unsigned char const *map, unsigned char Pix_x,unsigned char Pix_y); void LCD_Write_12X16FontS(unsigned char x,unsigned char y,unsigned char *c); void LCD_Write_12X16FontS_TB(unsigned char x,unsigned char y,unsigned char *c); #endif /* LCD5110_H_ */ /* * Nokia5110.c * * Created on: 2014-10-26 * Author: xiongpb */ //------------------------------------------------------------------- // Nokia5510指令集 // D7 D6 D5 D4 D3 D2 D1 D0 // 0 0 1 0 0 PD V H // | | |_______1->扩展指令集 0->基本指令集 // | |___________1->垂直寻址 0->水平寻址 // |_______________1->低功耗模式 0->正常模式 //------------------------------------------------------------------- // 显示模式 // D7 D6 D5 D4 D3 D2 D1 D0 // 0 0 0 0 1 D 0 E // | |_______0 0 1 1 7 // |_______________0 1 0 1 // 白屏 正常 全显 反转 //------------------------------------------------------------------- /******************************************************* 文件名 : Nokia5110Lcd.c 描述 : 诺基亚 5110 LCD 驱动源文件 作者 : xiongpb 编辑器 : CCS5.3 日期 : 2014-10-25 *******************************************************/ #include\"LCD5110.h\" #include /***************************************************************************************** * 函数名称:LCD5110_IO_Init() * 函数功能:I0口初始化 * 入口参数:无 * 出口参数:无 * 说明:无 *****************************************************************************************/ void LCD5110_IO_Init() { /* P6DIR |=BIT5; P3DIR |=BIT4; P3DIR |=BIT3; P1DIR |=BIT6; P6DIR |=BIT6;*/ P2DIR |=BIT2; P7DIR |=BIT4; P8DIR |=BIT1; P4DIR |=BIT3; P4DIR |=BIT0; } /***************************************************************************************** 8 * 函数名称:LCD5110_Init(void) * 函数功能:5110初始化 * 入口参数:无 * 出口参数:无 * 说明:无 *****************************************************************************************/ void LCD5110_Init(void) { LCD5110_IO_Init(); //I0口初始化 LCD_RST_L; // 产生一个让LCD复位的低电平脉冲 delay_us(150); LCD_RST_H; LCD_CE_H; delay_ms(1); LCD_CE_L; //5110片选有效,允许输入数 //设置LCD LCD_write_byte(0x21, DC_CMD); //使用扩展命令设置LCD模式 LCD_write_byte(0xC8, DC_CMD); //设置偏置电压 LCD_write_byte(0x06, DC_CMD); //温度校正 LCD_write_byte(0x13, DC_CMD); //1:48 LCD_write_byte(0x20, DC_CMD); //使用基本命令。并设置V=0,水平寻址 LCD5110_Clear(); //清屏 LCD_write_byte(0x0C, DC_CMD); //设定显示模式,正常显示 LCD5110_SetContrast(70); //对比度为68 LCD_CE_L; // 关闭LCD } /***************************************************************************************** * 函数名称:LCD5110_SetContrast(unsigned char contrast) * 函数功能:设置LCD对比度 * 入口参数:contrast 对比度(范围: 0~127) * 出口参数:无 * 说明:无 9 *****************************************************************************************/ void LCD5110_SetContrast(unsigned char contrast) { LCD_write_byte(0x21, DC_CMD); LCD_write_byte(0x80 | contrast, DC_CMD); LCD_write_byte(0x20, DC_CMD); } /***************************************************************************************** * 函数名称:LCD_write_byte(unsigned char data, DCType dc) * 函数功能:向LCD发送数据 * 入口参数:data:数据 dc:DC_CMD = 0//写命令 DC_DATA = 1 //写数据 * 出口参数:无 * 说明:无 *****************************************************************************************/ void LCD_write_byte(unsigned char data, DCType dc) { unsigned char i; LCD_CE_L; //5110片选有效,允许输入数据 if (dc==DC_CMD) LCD_DC_L; //发送命令 else LCD_DC_H; //发送数据 for(i=0;i<8;i++) //传送8bit数据 { if(data&0x80) LCD_DIN_H; else LCD_DIN_L; LCD_CLK_L; data = data << 1; LCD_CLK_H; } LCD_CE_H; //禁止5110 } /****************************************************************************************** 10 * 函数名:LCD_Set_XY * 功能: 设置LCD坐标 * 参数: X:0-83 Y:0-5 * 返回值:无 * 备 注: ******************************************************************************************/ void LCD_Set_XY(unsigned char X, unsigned char Y) { LCD_write_byte(0x40 | Y,DC_CMD);// column 列 LCD_write_byte(0x80 | X,DC_CMD);// row 行 } /***************************************************************************************** * 函数名称:LCD5110_Clear(void) * 函数功能: LCD清屏函数 * 入口参数:无 * 出口参数:无 * 说明:无 *****************************************************************************************/ void LCD5110_Clear(void) { unsigned char t; unsigned char k; LCD_Set_XY(0, 0);//设置RAM起始地址 for(t=0;t<6;t++) { for(k=0;k<84;k++) { LCD_write_byte(0x00, DC_DATA); } } } /***************************************************************************************** * 函数名称:void LCD_WriteChar(unsigned char x,unsigned char y,unsigned char c) * 函数功能: LCD清屏函数 * 入口参数:无 11 * 出口参数:无 * 说明:无 *****************************************************************************************/ void LCD_WriteChar(unsigned char x,unsigned char y,unsigned char c) { unsigned char i; c -= 32; //数组的行号 LCD_Set_XY(x,y); for(i=0; i<12; i++) { LCD_write_byte(font6x12[c][i], DC_DATA); if(i==5) { y++; LCD_Set_XY(x,y); } } } /* ********************************************************** *函数名:LCD_WriteString *功能: LCD写6X8的字符串 *参数:X , Y , S *返回值:无 备 注: ********************************************************** */ void LCD_WriteString(unsigned char X,unsigned char Y,char *s) { while(*s) { LCD_WriteChar(X,Y,*s); s++; X += 6; } } /* *************************************************************** 12 *函数名:LCD_WriteNum(unsigned int num) *功能:写入数字 *参数:num *返回值:无 **************************************************************** */ void LCD_WriteNum(unsigned char X,unsigned char Y,unsigned int num) { unsigned char str[8],i=0,len=0; unsigned int temp; temp = num; while(temp) { temp /=10; len++; } if(!num) { len++; str[0]=0x30; } str[len] = 0; while(num) { str[len-i-1] = num%10 + 0x30; num /=10; i++; } LCD_WriteString(X,Y,(char *)str); } /* ********************************************************** *函数名:LCD_Write_16X16Font *功能: 写一个16X16的汉字 *参数:x , y , c[2] x:0-83 y:0-5 *返回值:无 *备 注: ********************************************************** */ void LCD_Write_12X16Font(unsigned char x,unsigned char y,unsigned char *c) { unsigned char i,k; LCD_Set_XY(x-12,y); 13 for(k=0; k<5; k++) //K的值表示汉字库最多存放的字的数量(可改大) { if((font12x16[k].Index[0]==c[0])&&(font12x16[k].Index[1]==c[1])) { for(i=0; i<24; i++) { LCD_write_byte(font12x16[k].Msk[i], DC_DATA); if(i==11) { y++; LCD_Set_XY(x-12,y); } } } } } /* ********************************************************** *函数名:LCD_Write_16X16FontS *功能: 写一串16X16的汉字 *参数:x , y , c[2] x:0-83 y:0-5 *返回值:无 *备 注: ********************************************************** */ void LCD_Write_12X16FontS(unsigned char x,unsigned char y,unsigned char *c) { while(*c) {LCD_Write_12X16Font((x=x+12), y, c); c += 2;} //一个汉字GB码由2个字节组成 } /* ********************************************************** *函数名:LCD_Write_16X16Font *功能: 取反写一个16X16的汉字 *参数:x , y , c[2] x:0-83 y:0-5 *返回值:无 *备 注: ********************************************************** */ void LCD_Write_12X16Font_TB(unsigned char x,unsigned char y,unsigned char *c) { 14 unsigned char i,k; LCD_Set_XY(x-12,y); for(k=0; k<5; k++) //K的值表示汉字库最多存放的字的数量(可改大) { if((font12x16[k].Index[0]==c[0])&&(font12x16[k].Index[1]==c[1])) { for(i=0; i<24; i++) { LCD_write_byte(~font12x16[k].Msk[i], DC_DATA); if(i==11) { y++; LCD_Set_XY(x-12,y); } } } } } /* ********************************************************** *函数名:LCD_Write_16X16FontS *功能:取反写一串16X16的汉字 *参数:x , y , c[2] x:0-83 y:0-5 *返回值:无 *备 注: ********************************************************** */ void LCD_Write_12X16FontS_TB(unsigned char x,unsigned char y,unsigned char *c) { while(*c) {LCD_Write_12X16Font_TB((x=x+12), y, c); c += 2;} //一个汉字GB码由2个字节组成 } /* ********************************************************** *函数名:LCD_DrawPicture *功能: 绘图 *参数: X、Y :位图绘制的起始X、Y坐标; *map :位图点阵数据; 15 Pix_x :位图像素(长) <=84 Pix_y :位图像素(宽) <=48 *返回值:无 *备 注: ********************************************************** */ void LCD_DrawPicture(unsigned char X,unsigned char Y,unsigned char const *map, unsigned char Pix_x,unsigned char Pix_y) { unsigned int i,n; unsigned char row; //计算位图所占行数 if (Pix_y%8==0) //如果为位图所占行数为整数 row=Pix_y/8; else row=Pix_y/8+1; //如果为位图所占行数不是整数 LCD_Set_XY(X,Y); for (n=0;n LCD_Set_XY(X+i,Y+n); LCD_write_byte(map[i+n*Pix_x], DC_DATA); } } } 16 /* * Key.h * * Created on: 2014-11-22 * Author: xiongpb */ #ifndef KEY_H_ #define KEY_H_ extern unsigned char Key_val,Key_val_r; void P_IODect(); void GPIO_init(); void WDT_init(); #endif /* KEY_H_ */ #include \"MSP430f5529.h\" #include\"Key.h\" #include\"LCD5110.h\" unsigned char Key_val,Key_val_r; /****************************************************************************************************** * 名 称:GPIO_Init() * 功 能:设定按键和LED控制IO的方向,启用按键IO的上拉电阻 * 入口参数:无 * 出口参数:无 * 说 明:无 * 范 例:无 ******************************************************************************************************/ void GPIO_init() { 17 //-----设定P1.0和P1.6的输出初始值----- P1DIR |= BIT0; //设定P1.0为输出 P8DIR |= BIT2; //设定P8.2为输出 P3DIR |= BIT7; //设定P3.7为输出 P1OUT |= BIT0; //设定P1.0初值 P4DIR |= BIT7; //设定P3.7为输出 P4OUT |= BIT7; //设定P1.0初值 //行扫描键P6.4,P7.0,P3.6,P3.5默认为输入且为1 } /****************************************************************************************************** * 名 称:WDT_init() * 功 能:设定WDT定时中断为16ms,开启WDT定时中断使能 * 入口参数:无 * 出口参数:无 * 说 明:WDT定时中断的时钟源选择ACLK,可以用LPM3休眠。 * 范 例:无 ******************************************************************************************************/ void WDT_init() { WDTCTL=WDT_ADLY_16; //-----设定WDT为16ms中断----- SFRIE1|=WDTIE; //-----WDT中断使能----- } /****************************************************************************************************** * 名 称:WDT_ISR() * 功 能:响应WDT定时中断服务 * 入口参数:无 * 出口参数:无 * 说 明:WDT定时中断独占中断向量,所以无需进一步判断中断事件,也无需人工清除标志位。 * 所以,在WDT定时中断服务子函数中,直接调用WDT事件处理函数就可以了。 * 范 例:无 ******************************************************************************************************/ #pragma vector=WDT_VECTOR __interrupt void WDT_ISR(void) 18 { P_IODect(); //启用Port1事件检测函数 } /****************************************************************************************************** * 名 称:P1_IODect() * 功 能:判断是否有键被按下,哪个键被按下,并调用相应IO的中断事件处理函数 * 入口参数:无 * 出口参数:无 * 说 明:必须用最近两次扫描的结果,才知道按键是否被按下 * 范 例:无 ******************************************************************************************************/ void P_IODect() { static unsigned char KEY_Now=0; //变量值出函数时需保留 unsigned char KEY_Past=0; KEY_Past=KEY_Now; Key_val=20; P8OUT&= ~BIT2; //设定P8.1=1 P3OUT |= BIT7; //设定P2.3=0 if((P6IN&BIT4)==0) Key_val=11; else if((P7IN&BIT0)==0) Key_val=12; else if((P3IN&BIT6)==0) Key_val=13; else if((P3IN&BIT5)==0) Key_val=14; P8OUT |=BIT2; //设定P8.1=1 P3OUT&= ~BIT7; //设定P2.3=0 if((P7IN&BIT0)==0) Key_val=15; else if((P3IN&BIT6)==0) Key_val=16; else if((P3IN&BIT5)==0) Key_val=17; //-----查询IO的输入寄存器----- if((10 19 按键按下 { //P4OUT ^= BIT7; Key_val_r=Key_val-10; } } #include \"MSP430f5529.h\" #include\"Key.h\" #include\"LCD5110.h\" unsigned char Key_val,Key_val_r; /****************************************************************************************************** * 名 称:GPIO_Init() * 功 能:设定按键和LED控制IO的方向,启用按键IO的上拉电阻 * 入口参数:无 * 出口参数:无 * 说 明:无 * 范 例:无 ******************************************************************************************************/ void GPIO_init() { //-----设定P1.0和P1.6的输出初始值----- P1DIR |= BIT0; //设定P1.0为输出 P8DIR |= BIT2; //设定P8.2为输出 P3DIR |= BIT7; //设定P3.7为输出 P1OUT |= BIT0; //设定P1.0初值 P4DIR |= BIT7; //设定P3.7为输出 P4OUT |= BIT7; //设定P1.0初值 //行扫描键P6.4,P7.0,P3.6,P3.5默认为输入且为1 } /*********************************************************************** 20 ******************************* * 名 称:WDT_init() * 功 能:设定WDT定时中断为16ms,开启WDT定时中断使能 * 入口参数:无 * 出口参数:无 * 说 明:WDT定时中断的时钟源选择ACLK,可以用LPM3休眠。 * 范 例:无 ******************************************************************************************************/ void WDT_init() { WDTCTL=WDT_ADLY_16; //-----设定WDT为16ms中断----- SFRIE1|=WDTIE; //-----WDT中断使能----- } /****************************************************************************************************** * 名 称:WDT_ISR() * 功 能:响应WDT定时中断服务 * 入口参数:无 * 出口参数:无 * 说 明:WDT定时中断独占中断向量,所以无需进一步判断中断事件,也无需人工清除标志位。 * 所以,在WDT定时中断服务子函数中,直接调用WDT事件处理函数就可以了。 * 范 例:无 ******************************************************************************************************/ #pragma vector=WDT_VECTOR __interrupt void WDT_ISR(void) { P_IODect(); //启用Port1事件检测函数 } /****************************************************************************************************** * 名 称:P1_IODect() * 功 能:判断是否有键被按下,哪个键被按下,并调用相应IO的中断事件处理函数 * 入口参数:无 * 出口参数:无 21 * 说 明:必须用最近两次扫描的结果,才知道按键是否被按下 * 范 例:无 ******************************************************************************************************/ void P_IODect() { static unsigned char KEY_Now=0; //变量值出函数时需保留 unsigned char KEY_Past=0; KEY_Past=KEY_Now; Key_val=20; P8OUT&= ~BIT2; //设定P8.1=1 P3OUT |= BIT7; //设定P2.3=0 if((P6IN&BIT4)==0) Key_val=11; else if((P7IN&BIT0)==0) Key_val=12; else if((P3IN&BIT6)==0) Key_val=13; else if((P3IN&BIT5)==0) Key_val=14; P8OUT |=BIT2; //设定P8.1=1 P3OUT&= ~BIT7; //设定P2.3=0 if((P7IN&BIT0)==0) Key_val=15; else if((P3IN&BIT6)==0) Key_val=16; else if((P3IN&BIT5)==0) Key_val=17; //-----查询IO的输入寄存器----- if((10 { //P4OUT ^= BIT7; Key_val_r=Key_val-10; } } /* * VS1003.c 22 * * Created on: 2015-4-12 * Author: xiongpb */ #include \"VS1003.h\" #include \"Soft_SPI.h\" /************************************************************************************************************ * 名 称:SPI_Init * 功 能:初始化SPI端口 * 入口参数:无 * 出口参数:无 * 说 明: 初始化SD卡为SPI模式 * 使用范例:SPI_Init(); ************************************************************************************************************/ void VS_IO_Init(void) { P2DIR|=BIT5+BIT6; //输出 P1DIR|=BIT0; //输出 P1DIR&=~BIT5; //输入 } /********************************************************************************* ** 函数名称: void VS_delay(INT16U time). ** 功能描述: SPI发送数据函数. ** 输入参数: INT16U time 时间长短. ** 输出参数: None. ** 返回参数: None. **********************************************************************************/ void VS_delay(unsigned int time) { while(time--); } /********************************************************************************* ** 函数名称: void VS_WriteByte(INT8U w_dat) . ** 功能描述: 向VS写字节函数. ** 输入参数: INT8U w_dat 要写入的字节. 23 ** 输出参数: None. ** 返回参数: None. **********************************************************************************/ void VS_WriteByte(unsigned char w_dat) { unsigned char sdat; sdat=w_dat; SPI_WriteByte(sdat); } /********************************************************************************* ** 函数名称: INT8U VS_ReadByte(void). ** 功能描述: 从VS芯片读字节函数. ** 输入参数: None. ** 输出参数: None. ** 返回参数: return (sdat) 读出的字节. **********************************************************************************/ unsigned char VS_ReadByte(void) { unsigned char sdat; sdat=SPI_ReadByte(); return (sdat); } /********************************************************************************* ** 函数名称: void VS_Write_Reg(INT8U addr,INT16U vsdata). ** 功能描述: 向VS1003写入数据. ** 输入参数: INT8U addr 功能寄存器的地址,INT16U vsdata 写入字节. ** 输出参数: None. ** 返回参数: None. **********************************************************************************/ void VS_Write_Reg( unsigned char addr,unsigned int vsdata) { // VS_DREQ=1; /* 51单片机IO作输入时先置为1 */ while(!VS_DREQ); /* VS的DREQ为高电平时才接收数据 */ VS_CS_L; /* 打开片选 */ 24 VS_WriteByte(VS_WRITE_CMD); /* 写入操作码(功能寄存器写操作) */ VS_WriteByte(addr); /* 写入寄存器地址 */ // VS_WriteByte(hdat); /* 写入高字节 */ // VS_WriteByte(ldat); /* 写入低字节 */ VS_WriteByte(vsdata>>8); VS_WriteByte(vsdata&0xff); VS_CS_H; /* 关闭片选 */ } /********************************************************************************* ** 函数名称: INT16U VS_Read_Reg(INT8U addr). ** 功能描述: 从VS的功能寄存器中读取数据,一个字. ** 输入参数: INT8U addr 功能寄存器的地址. ** 输出参数: None. ** 返回参数: return temp读到的字,2字节. **********************************************************************************/ unsigned int VS_Read_Reg( unsigned char addr) { unsigned int temp=0; // VS_DREQ=1; while(!VS_DREQ); /* VS的DREQ为高电平时才接收数据 */ VS_CS_L; /* 打开片选 */ VS_WriteByte(VS_Read); /* 读出操作码(功能寄存器读操作) */ VS_WriteByte(addr); /* 写入寄存器地址 */ temp =VS_ReadByte(); /* 读高字节 */ temp<<=8; temp|=VS_ReadByte(); /* 读取低字节,与高字节拼成一个字 */ VS_CS_H; /* 关闭片选 */ return temp; } /********************************************************************************* ** 函数名称: void VsSetVolume(INT8U volume) . ** 功能描述: 设置音量 1 - 48. ** 输入参数: INT8U volume 1 - 48 . ** 输出参数: None. ** 返回参数: None. **********************************************************************************/ void VsSetVolume( unsigned char volume) 25 { volume = volume * 0x03; VS_Write_Reg(VS_VOL,((volume<<8)|volume)); } /********************************************************************************* ** 函数名称: void VS_Init(void). ** 功能描述: VS1003软复位及初始化. ** 输入参数: None. ** 输出参数: None. ** 返回参数: None. **********************************************************************************/ void VS_Init(void) { VS_IO_Init(); VS_RST_H; VS_delay(100); VS_RST_L; VS_delay(100); VS_RST_H; /* 硬件复位,VS_RST低电平有效 */ VS_delay(100); VS_Write_Reg(VS_MODE ,0x0804); /* 软件复位,向0号寄存器写入0x0804 SM_SDINEW为1 SM_RESET为1 */ VS_Write_Reg(VS_CLOCKF,0x9800); /* 时钟设置,向3号寄存器写入0x9800 SC_MULT 为4 SC_ADD 为3 SC_FREQ为0 */ VS_Write_Reg(VS_VOL ,0x7070); /* 音量设置,左右声道均中等音量 */ VS_Write_Reg(0x02 ,0x7aaa); VS_DCS_L; /* 打开数据片选 */ VS_WriteByte(0); /* 写入数据,这里写入4个0,是无关数据,用来启动数据传输 */ VS_WriteByte(0); VS_WriteByte(0); VS_WriteByte(0); VS_DCS_H; /* 关闭数据片选 */ } /********************************************************************************* ** 函数名称: void VS_Send_Dat32(INT8U *dat) . ** 功能描述: 向VS1003写入32个字节的音频数据. 26 ** 输入参数: INT8U *dat 音频数据. ** 输出参数: None. ** 返回参数: None. **********************************************************************************/ void VS_Send_Dat32( unsigned char *dat) { unsigned char i=0; // VS_DREQ=1; VS_DCS_L; /* 打开数据片选,即开启SDI传输 */ while(!VS_DREQ); /* VS1003的DREQ为高才能写入数据 */ for(i=0;i<32;i++) VS_WriteByte(*(dat+i)); /* 通过SPI向VS1003写入32个字节的音频数据 */ VS_DCS_H; /* 打开数据片选,即开启SDI传输 */ } /********************************************************************************* ** 函数名称: void VS_Flush_Buffer(void). ** 功能描述: 向VS1003写入2048个0,清空缓冲,为下一首mp3做准备. ** 输入参数: None. ** 输出参数: None. ** 返回参数: None. **********************************************************************************/ void VS_Flush_Buffer(void) { unsigned char i,j=0; VS_DCS_L; /* 打开数据片选,即开启SDI传输 */ for(i=0;i<;i++) { // VS_DREQ=1; while(!VS_DREQ); /* VS1003的DREQ为高才能写入数据 */ for(j=0;j<32;j++) VS_WriteByte(0); /* 通过SPI向VS1003写入32个字节的0 */ } VS_DCS_H; /* 关闭数据片选 */ } /********************************************************************************* 27 ** 函数名称: void VS_SinTest(INT8U x). ** 功能描述: 正弦测试函数,检查vs1003是否正常. ** 输入参数: INT8U x 正弦波频率. ** 输出参数: None. ** 返回参数: None. **********************************************************************************/ void VS_SinTest(int x) { VS_Write_Reg(0x00,0x0820); /* 启动测试,向0号寄存器写入0x0820 SM_SDINEW为1 SM_TEST为1 */ // VS_DREQ=1; while(!VS_DREQ); /* 等待DREQ变为高电平 */ VS_DCS_L; /* 打开数据片选 */ VS_WriteByte(0x53); /* 写入以下8个字节,进入正弦测试 */ VS_WriteByte(0xef); VS_WriteByte(0x6e); VS_WriteByte(x); /* 参数x用来调整正弦测试中正弦波的频率 */ VS_WriteByte(0); VS_WriteByte(0); VS_WriteByte(0); VS_WriteByte(0); VS_delay(60000); /* 这里延时一段时间,可以听到“正弦音” */ VS_delay(60000); VS_delay(60000); VS_delay(60000); VS_delay(60000); VS_delay(60000); VS_WriteByte(0x45); /* 写入以下8个字节,退出正弦测试 */ VS_WriteByte(0x78); VS_WriteByte(0x69); VS_WriteByte(0x74); VS_WriteByte(0); VS_WriteByte(0); VS_WriteByte(0); VS_WriteByte(0); VS_DCS_H; /* 关闭数据片选 */ } /* 28 * SPI.h * * Created on: 2015-4-12 * Author: xiongpb */ #ifndef SPI_H_ #define SPI_H_ #include #define SOFT_SPI //条件编译,SOFT_SPI启用软件SPI代码 extern void SPI_CS_High(void); extern void SPI_CS_Low(void); extern void SPI_HighSpeed(void); extern void SPI_LowSpeed(void); extern void SPI_init(void); extern unsigned char SPI_TxFrame(unsigned char *pBuffer, unsigned int size); extern unsigned char SPI_RxFrame(unsigned char *pBuffer, unsigned int size); #endif /* SPI_H_ */ /***************************************************************************//** * @file HAL_SDCard.c * @addtogroup HAL_SDCard * @{ ******************************************************************************/ #include \"msp430.h\" #include \"SPI.h\" // Pins from MSP430 connected to the SD Card #define SPI_SIMO BIT1 #define SPI_SOMI BIT2 #define SPI_CLK BIT3 #define SD_CS BIT7 // Ports #define SPI_SEL P4SEL #define SPI_DIR P4DIR 29 #define SPI_OUT P4OUT #define SPI_REN P4REN #define SD_CS_SEL P3SEL #define SD_CS_OUT P3OUT #define SD_CS_DIR P3DIR /***************************************************************************//** * @brief Initialize SD Card * @param None * @return None ******************************************************************************/ void SPI_init(void) { // Port initialization for SD Card operation SPI_SEL |= SPI_CLK + SPI_SOMI + SPI_SIMO; SPI_DIR |= SPI_CLK + SPI_SIMO; SPI_REN |= SPI_SOMI; // Pull-Ups on SD Card SOMI SPI_OUT |= SPI_SOMI; // Certain SD Card Brands need pull-ups SD_CS_SEL &= ~SD_CS; SD_CS_OUT |= SD_CS; SD_CS_DIR |= SD_CS; // Initialize USCI_B1 for SPI Master operation UCB1CTL1 |= UCSWRST; // Put state machine in reset UCB1CTL0 = UCCKPL + UCMSB + UCMST + UCMODE_0 + UCSYNC; // 3-pin, 8-bit SPI master // Clock polarity select - The inactive state is high // MSB first UCB1CTL1 = UCSWRST + UCSSEL_2; // Use SMCLK, keep RESET UCB1BR0 = 63; // Initial SPI clock must be <400kHz UCB1BR1 = 0; // f_UCxCLK = 25MHz/63 = 397kHz UCB1CTL1 &= ~UCSWRST; // Release USCI state machine 30 UCB1IFG &= ~UCRXIFG; } /***************************************************************************//** * @brief Enable low fast SD Card SPI transfers. This function is typically * called after the initial SD Card setup is done to maximize * transfer speed. * @param None * @return None ******************************************************************************/ void SPI_LowSpeed(void) { UCB1CTL1 |= UCSWRST; // Put state machine in reset UCB1BR0 =63; // f_UCxCLK = 25MHz/2 = 12.5MHz UCB1BR1 = 0; UCB1CTL1 &= ~UCSWRST; // Release USCI state machine } /***************************************************************************//** * @brief Enable fast SD Card SPI transfers. This function is typically * called after the initial SD Card setup is done to maximize * transfer speed. * @param None * @return None ******************************************************************************/ void SPI_HighSpeed(void) { UCB1CTL1 |= UCSWRST; // Put state machine in reset UCB1BR0 = 2; // f_UCxCLK = 25MHz/2 = 12.5MHz UCB1BR1 = 0; UCB1CTL1 &= ~UCSWRST; // 31 Release USCI state machine } /***************************************************************************//** * @brief Read a frame of bytes via SPI * @param pBuffer Place to store the received bytes * @param size Indicator of how many bytes to receive * @return None ******************************************************************************/ unsigned char SPI_RxFrame(unsigned char *pBuffer, unsigned int size) { uint16_t gie = __get_SR_register() & GIE; // Store current GIE state __disable_interrupt(); // Make this operation atomic UCB1IFG &= ~UCRXIFG; // Ensure RXIFG is clear // Clock the actual data transfer and receive the bytes while (size--){ while (!(UCB1IFG & UCTXIFG)) ; // Wait while not ready for TX UCB1TXBUF = 0xff; // Write dummy byte while (!(UCB1IFG & UCRXIFG)) ; // Wait for RX buffer (full) *pBuffer++ = UCB1RXBUF; } __bis_SR_register(gie); // Restore original GIE state return 0; } /***************************************************************************//** * @brief Send a frame of bytes via SPI * @param pBuffer Place that holds the bytes to send 32 * @param size Indicator of how many bytes to send * @return None ******************************************************************************/ unsigned char SPI_TxFrame(unsigned char *pBuffer, unsigned int size) { uint16_t gie = __get_SR_register() & GIE; // Store current GIE state __disable_interrupt(); // Make this operation atomic // Clock the actual data transfer and send the bytes. Note that we // intentionally not read out the receive buffer during frame transmission // in order to optimize transfer speed, however we need to take care of the // resulting overrun condition. while (size--){ while (!(UCB1IFG & UCTXIFG)) ; // Wait while not ready for TX UCB1TXBUF = *pBuffer++; // Write byte } while (UCB1STAT & UCBUSY) ; // Wait for all TX/RX to finish UCB1RXBUF; // Dummy read to empty RX buffer // and clear any overrun conditions __bis_SR_register(gie); // Restore original GIE state return 0; } /***************************************************************************//** * @brief Set the SD Card's chip-select signal to high * @param None * @return None ******************************************************************************/ 33 void SPI_CS_High(void) { SD_CS_OUT |= SD_CS; } /***************************************************************************//** * @brief Set the SD Card's chip-select signal to low * @param None * @return None ******************************************************************************/ void SPI_CS_Low(void) { SD_CS_OUT &= ~SD_CS; } /***************************************************************************//** * @} ******************************************************************************/ /* * Soft_SPI.h * * Created on: 2015-4-12 * Author: xiongpb */ #ifndef SOFT_SPI_H_ #define SOFT_SPI_H_ #include \"msp430.h\" //sbit SPI_SCL=P40; //SPI同步时钟 输出 #define SPI_SCK_H P4OUT|=BIT0 #define SPI_SCK_L P4OUT&=~BIT0 34 //sbit SPI_SI =P42; //SPI同步数据 输出 #define SPI_SI_H P3OUT|=BIT5 #define SPI_SI_L P3OUT&=~BIT5 //sbit SPI_SO =P1^6; //SPI同步数据 输入 #define SPI_SO_IN P1IN&BIT6 extern void SPI2_Init(void); extern void SPI_WriteByte(unsigned char x); extern unsigned char SPI_ReadByte(); #endif /* SOFT_SPI_H_ */ /* * Soft_SPI.c * * Created on: 2015-4-12 * Author: xiongpb */ #include \"Soft_SPI.h\" /************************************************************************************************************ * 名 称:SPI_Init * 功 能:初始化SPI端口 * 入口参数:无 * 出口参数:无 * 说 明: 初始化SD卡为SPI模式 * 使用范例:SPI_Init(); ************************************************************************************************************/ void SPI2_Init(void) { P3DIR|=BIT5; //输出 P4DIR|=BIT0; //输出 P1DIR&=~BIT6; //输入 SPI_SCK_H; } /************************************************************************************************************ * 名 称:SPI_WriteByte * 功 能:SPI发送1个字节 * 入口参数:x:待发送字节 35 * 出口参数:无 * 说 明: 无 * 使用范例:无 ************************************************************************************************************/ void SPI_WriteByte(unsigned char x) { unsigned char i,data; data=x; for(i=0;i<8;i++) { SPI_SCK_L; if(data&BIT7) SPI_SI_H; else SPI_SI_L; SPI_SCK_H; data<<=1; } } /************************************************************************************************************ * 名 称:SPI_ReadByte * 功 能:SPI接收1个字节 * 入口参数:无 * 出口参数:x:待接收字节 * 说 明: 无 * 使用范例:无 ************************************************************************************************************/ unsigned char SPI_ReadByte() { unsigned char i,data; for(i=0;i<8;i++) { SPI_SCK_L; if(SPI_SO_IN) { data<<=1; data=data+BIT0; } else 36 data<<=1; SPI_SCK_H; } return data; } /* * SD_SPI.h * * Created on: 2015-4-12 * Author: xiongpb */ #ifndef SD_SPI_H_ #define SD_SPI_H_ extern unsigned char SD_Init(); extern unsigned char SD_Reset(); extern unsigned char SD_Read_Sector(unsigned long Addr ,unsigned char *Ptr,unsigned int FirstNum,unsigned int Num); extern unsigned char SD_Write_Sector(unsigned long Addr ,unsigned char *Ptr,unsigned int FirstNum,unsigned int Num); extern unsigned char SD_Set_SPI(); #endif /* SD_SPI_H_ */ /* * SD_SPI.c * * Created on: 2015-4-12 * Author: xiongpb */ /* * SD_SPI.c *说明:该函数库为通用SD卡读写顶层库函数。 * 用户只需要更改“SD_HardWare.c”中的少量底层代码,即可移植到任何处理器上。 * Created on: 2013-3-4 * */ #include\"SD_HardWare.h\" 37 #include \"SD_SPI.h\" #include\"SPI.h\" //-----SD 卡相关的命令宏定义----- #define SD_WRITE_DELAY 钟 100 // 先发74个以上的时 #define SD_EMPTY_CLK 0xFF #define SD_EMPTY_DATA 0xFF #define SD_SPI_CRC 0xFF //SPI模式下CRC无效,随便给 #define SD_CMD0_CRC 0x95 //复位命令CMD0的CRC校验码 #define SD_CMD0 0+0x40 //复位命令 #define SD_CMD1 1+0x40 //SPI模式命令 #define SD_CMD17 17+0x40 //读扇区命令 #define SD_CMD24 24+0x40 //写扇区命令 #define SD_CMD41 41+0x40 //初始化扇区命令 #define SD_CMD55 55+0x40 //初始化扇区命令 //-----SD卡相关应答----- #define SD_COMMAND_ACK 0x00 //命令应答 #define SD_RESET_ACK 0x01 //复位应答 #define SD_DATA_ACK 0xFE //数据应答 #define SD_WRITE_ACK 0x05 //写扇区应答 //----系统超时控制---- #define SD_TIMEOUT 100 #define TIMEOUT 200 /************************************************************************************************************ * 名 称:Write_Command_SD() * 功 能:SD卡在SPI模式下,向SD卡中写入6个字节的命令 * 入口参数:CMD:指向存放六个字节命令的数组 * 出口参数:SD 卡应答值 * 说 明: 向SD卡中一次写入六个字节的命令 * 使用范例:Write_Command_SD(CMD); ************************************************************************************************************/ unsigned char Write_Command_SD(unsigned char *CMD) { unsigned char tmp=0; unsigned char i = 0; SD_CS_High(); //-----先发8个空clock----- SD_Write_Byte(0xFF); SD_CS_Low(); 38 //-----写入6个字节的命令字帧----- SD_Write_Frame(CMD,6); //-----空第一次,即忽略第一个返回值----- SD_Read_Byte(); i = SD_TIMEOUT; do { tmp = SD_Read_Byte(); i--; } while((tmp==0xff)&&i); return(tmp); } /************************************************************************************************************ * 名 称:SD_Write_Sector * 功 能:SD卡在SPI模式下,向SD卡中,在指定的位置写入指定个数的数据。 * 入口参数:Addr:物理扇区的地址 * *Ptr:指向待写数据的数据缓存 * FirstNum:写入该扇区的首个字节偏移地址 * Num:此次操作要写入的数据个数 (FirstNum+Num<512) * 出口参数:0:写入失败 * 1:写入成功 * 使用范例:SD_Write_Sector(83241,buffer,0,100); //向扇区83241中写入100个字节 ************************************************************************************************************/ unsigned char SD_Write_Sector(unsigned long Addr ,unsigned char *Ptr,unsigned int FirstNum,unsigned int Num) { unsigned char temp=0; unsigned int EndNum = 0; unsigned int i=0; unsigned char CMD[6]={0}; //-----发送命令----- CMD[0]=SD_CMD24; //-----将32位地址拆分------ Addr = Addr <<9; //sector = sector*512 将物理地址转换为逻辑地址;(注意一定需要此处的转换) CMD[1]=((Addr&0xFF000000)>>24); CMD[2]=((Addr&0x00FF0000)>>16); CMD[3]=((Addr&0x0000FF00)>>8); CMD[4]=Addr&0x000000FF; 39 //-----CRC校验,SPI模式下无效,可随便给----- CMD[5]=SD_SPI_CRC; //----等待SD卡应答---- i=TIMEOUT; 门限值 do{ temp = Write_Command_SD(CMD); i--; }while((temp != SD_COMMAND_ACK)&&i); //超时判断 if (i==0) return(0); 时,返回失败代码 //----空发若干次CLK---- for(i=0;i //SD_Write_Frame(pTemp,SD_WRITE_DELAY); //-----发送数据头字节----- SD_Write_Byte(SD_DATA_ACK); // //-----发送512字节数据,含空数据---- EndNum=FirstNum+Num; for(i=0;i SD_Write_Byte(SD_EMPTY_DATA ); } SD_Write_Frame(Ptr,Num); //写有效数据 for(i=0;i<512-EndNum;i++) { //-----写空数据----- SD_Write_Byte(SD_EMPTY_DATA ); } //-----发送两个字节的校验位----- SD_Write_Byte(0xff); SD_Write_Byte(0xff); //-----判断SD的应答是否为xxx00101b------- temp=SD_Read_Byte(); temp =temp &0x01F; if(temp != SD_WRITE_ACK) { SD_CS_High(); return(0); //超时 //超 40 } //-------一直发CLK,直到不BUSY------ i=TIMEOUT; //超时门限值 do{ i--; }while(SD_Read_Byte() != 0xff &&i); //超时判断 if (i==0) { SD_CS_High(); return(0); //超时,返回失败代码 } //---成功完成写数据,将片选CS拉高------ SD_CS_High(); return 1; } /************************************************************************************************************ * 名 称:SD_Read_Sector * 功 能:SD卡在SPI模式下,从SD卡中,在指定的位置处,读出指定个数的数据到缓存。 * 入口参数:Addr:物理扇区的地址 * *Ptr:指向存放读取数据的数据缓存 * FirstNum:从该扇区读取首个字节的偏移地址 * Num:此次操作要读取的数据个数 (FirstNum+Num<512) * 出口参数:0:读取失败 * 1:读取成功 * 使用范例:SD_Read_Sector(83241,buffer,0,100); //从扇区83241中读出100个字节,放入buffer中 ************************************************************************************************************/ unsigned char SD_Read_Sector(unsigned long Addr ,unsigned char *Ptr,unsigned int FirstNum,unsigned int Num) { unsigned char temp=0; unsigned int i=0; unsigned int EndNum=0; unsigned char CMD[6]={0}; //-----命令17----- CMD[0]=SD_CMD17; 41 //-----将32位地址拆分------ Addr = Addr <<9; //sector = sector*512 将物理地址转换为逻辑地址; CMD[1]=((Addr&0xFF000000)>>24); CMD[2]=((Addr&0x00FF0000)>>16); CMD[3]=((Addr&0x0000FF00)>>8); CMD[4]=Addr&0x000000FF; //-----CRC校验,SPI模式下无效,可随便给----- CMD[5]=SD_SPI_CRC; //----等待SD卡应答---- i=TIMEOUT; 限值 do{ temp = Write_Command_SD(CMD); i--; }while((temp!=SD_COMMAND_ACK)&&i); if (i==0) { SD_CS_High(); return(0); 时,返回失败代码 } //----等待SD卡应答-------------- i=TIMEOUT; 限值 do{ temp = SD_Read_Byte(); i--; }while(( temp !=SD_DATA_ACK)&&i); if (i==0) { SD_CS_High(); return(0); 时,返回失败代码 } //-----读取指定字节----- EndNum=FirstNum+Num; for(i=0;i //超时判断 //超时判断 //超时门 //超 //超时门 //超 42 SD_Read_Frame(Ptr,Num); //读取有效字节 for(i=0;i<512-EndNum;i++) { //-----空读(放弃存储)其他字节----- SD_Read_Byte(); } //-----空读两次 CRC--Byte----- SD_Read_Byte(); SD_Read_Byte(); SD_CS_High(); return (1); } /************************************************************************************************************ * 名 称:SD_Init * 功 能:初始化SD卡为SPI模式 * 入口参数:无 * 出口参数:0:初始化失败 * 1:初始化成功 * 说 明: 初始化SD卡为SPI模式 * 使用范例:SD_Init(); ************************************************************************************************************/ unsigned char SD_Init() { unsigned char temp =0 ; //-----初始化之前,先将SPI设为低速(SPI_clk=300K左右)----- SD_Low_Speed(); //-----复位SPI----- temp = SD_Reset(); if(temp==0) return(0); //-----设定SD为SPI都取名模式----- temp = SD_Set_SPI(); if(temp==0) return(0); //--初始化完成以后,将SPI速度提到高速(10Mhz左右)上来,便于快速读写扇区----- SD_High_Speed(); return(1); } /************************************************************************************************************ 43 * 名 称:SD_Reset() * 功 能:复位SD卡 * 入口参数:无 * 出口参数:0:复位SD失败 * 1:复位SD成功 * 说 明: 上电后SD卡位SD模式,需先复位后才能设置为SPI模式 * 使用范例:无 ************************************************************************************************************/ unsigned char SD_Reset() { unsigned char i=0,temp = 0; unsigned char CMD[6] = {SD_CMD0,0x00,0x00,0x00,0x00,SD_CMD0_CRC}; SD_CS_High(); //CS片选使能 for(i=0;i<0x0f;i++) //空发80个CLK(10字节) { SD_Write_Byte(SD_EMPTY_CLK); } i=TIMEOUT; //超时门限值 do{ temp = Write_Command_SD(CMD); //CMD0 i--; }while((temp != SD_RESET_ACK) && i); //超时判断 if(i==0) return(0); //超时,返回失败代码 else return (1); } /************************************************************************************************************ * 名 称:SD_Set_SPI() * 功 能:将SD卡设为SPI模式 * 入口参数:无 * 出口参数:0:复位SD失败 * 1:复位SD成功 * 说 明: 需先复位操作后才能进行设置SPI模式操作 * 使用范例:无 ************************************************************************************************************/ 44 unsigned char SD_Set_SPI() { unsigned char i=0,temp=0; unsigned char CMD[6]={0}; //-----拆分命令为4个字节----- CMD[0]= SD_CMD1; CMD[1]= ((0x00ffc000 & 0xff000000) >>24); CMD[2]= ((0x00ffc000 & 0x00ff0000) >>16); CMD[3]= ((0x00ffc000 & 0x0000ff00) >>8); CMD[4]= 0x00ffc000 & 0x000000ff; CMD[5]= SD_SPI_CRC; i=TIMEOUT; //超时门限值 do{ CMD[0] = SD_CMD55; //CMD55命令 temp = Write_Command_SD(CMD); 送 CMD55 //-----判断是否为SD卡----- if(temp == 0x01) //如果有反应 { // //-----如无需判断存储卡类型,直接执行线间代码----- CMD[0] = SD_CMD41; //CMD41命令 temp = Write_Command_SD(CMD); CMD41进行激活 if(temp == 0x00) { SD_CS_High(); //CS片选禁能 } // //--------------------------------------------------- } //-----否则,为MMC卡----- else //如果发送CMD55无反应,改发送CMD1 { CMD[0] = SD_CMD1; //CMD1命令 CMD[5] = 0xFF; temp = Write_Command_SD(CMD); //先发 //发送 //发送 45 CMD1进行激活 if(temp == 0x00) { SD_CS_High(); //CS片选禁能 } } i--; }while((temp !=SD_COMMAND_ACK)&&i); //超时判断 if(i==0) return(0); //超时,返回失败代码 else return (1); } /* * SD_HardWare.h * * Created on: 2015-4-12 * Author: xiongpb */ #ifndef SD_HARDWARE_H_ #define SD_HARDWARE_H_ extern void SD_Write_Byte(unsigned char Value); extern void SD_Write_Frame(unsigned char *pBuffer,unsigned char size); extern void SD_CS_High(); extern void SD_CS_Low(); extern unsigned char SD_Read_Byte(); extern void SD_Read_Frame(unsigned char *pBuffer, unsigned int size); extern void SD_High_Speed(); extern void SD_Low_Speed(); #endif /* SD_HARDWARE_H_ */ 46 /* * SD_HardWare.c * * Created on: 2015-4-12 * Author: xiongpb */ /* * SD_HardWare.c *说明:此函数库文件为SD卡底层相关的读写和操作函数,也是与最底层G2的SPI唯一的衔接函数库。 * 若是需要在其他硬件微处理器上使用上层SD_SPI.c库函数,只需要更改此函数库中带有 * “此处,调用底层G2硬件接口函数”注释的4处底层SPI函数,和SD_High_Speed()、 * SD_Low_Speed()这两个函数即可完成移植。 * Created on: 2013-4-3 * */ #include\"MSP430.h\" #include\"SPI.h\" /**************************************************************************** * 名 称:SD_High_Speed() * 功 能:SD卡在SPI读取模式下,使能SPI的时钟为高速传输模式 * 入口参数:无 * 出口参数:无 * 说 明: 该函数可以更改当前SPI工作的速度。 一般在初始化完SD卡后 * 需要将SPI的速度提高,加快读写速度 * 使用范例:SD_High_Speed(); ****************************************************************************/ void SD_High_Speed() { SPI_HighSpeed(); } /**************************************************************************** * 名 称:SD_Low_Speed() * 功 能:SD卡在SPI读取模式下,使能SPI的时钟为低速(300K左右) * 入口参数:无 * 出口参数:无 47 * 说 明: 由于在初始化完SD卡时,需要的速度很低,此函数更改当前 * SPI工作的速度。使其在300K左右 * 使用范例:SD_Low_Speed(); ****************************************************************************/ void SD_Low_Speed() { SPI_LowSpeed(); } /**************************************************************************** * 名 称:SD_CS_High() * 功 能:SD卡在SPI读取模式下,控制使能CS管脚为高电平 * 入口参数:无 * 出口参数:无 * 说 明: 此处的CS管脚可以根据硬件的需要,任意指定管脚作CS均可。 * 使用范例:SD_CS_High(); ****************************************************************************/ void SD_CS_High() { //-----此处,调用底层G2硬件接口函数----- SPI_CS_High(); } /**************************************************************************** * 名 称:SD_CS_Low() * 功 能:SD卡在SPI读取模式下,控制使能CS管脚为低电平 * 入口参数:无 * 出口参数:无 * 说 明:: 此处的CS管脚可以根据硬件的需要,任意指定管脚作CS均可。 * 使用范例:SD_CS_Low(); ****************************************************************************/ void SD_CS_Low() { //-----此处,调用底层G2硬件接口函数----- SPI_CS_Low(); } /**************************************************************************** * 名 称:SD_Write_Byte() * 功 能:SPI模式下,向SD卡中写入一个字节数据 48 * 入口参数:value:当前要写入的数据 * 出口参数:无 * 说 明:使用该函数可以向SD卡中写入一个字节 * 使用范例:SD_Write_Byte();// 将value写入SD 卡中 ****************************************************************************/ void SD_Write_Byte(unsigned char value) { unsigned char temp=0; do{ //-----此处,调用底层G2硬件接口函数----- temp=SPI_TxFrame(&value,1); }while(temp==0); } /**************************************************************************** * 名 称:SD_Write_Frame() * 功 能:SPI模式下,向SD卡中写入size个字节数据 * 入口参数:pBuffer:当前要写入的数据头指针 * size:计划要写入的数据个数 * 出口参数:无 * 说 明:使用该函数可以向SD卡中写入size个字节 * 使用范例:无 ****************************************************************************/ void SD_Write_Frame(unsigned char *pBuffer,unsigned int size) { unsigned char temp=0; do{ //-----此处,调用底层G2硬件接口函数----- temp=SPI_TxFrame(pBuffer,size); }while(temp==0); } /**************************************************************************** * 名 称:SD_Read_Frame() * 功 能:SPI模式下,从SD卡中读出size个字节数据 * 入口参数:pBuffer:存储的读SD数据的头指针 * size:计划要读取的数据个数 * 出口参数:无 * 说 明:使用该函数可以从SD卡中读出size个字节 * 使用范例:无 ****************************************************************************/ 49 void SD_Read_Frame(unsigned char *pBuffer, unsigned int size) { unsigned char temp=0; do{ //-----此处,调用底层G2硬件接口函数----- temp=SPI_RxFrame(pBuffer,size); }while(temp==0); } /**************************************************************************** * 名 称:SD_Read_Byte() * 功 能:SPI模式下,读取SD卡中的一个字节 * 入口参数:无 * 出口参数:value:当前读取出的数据 * 说 明:使用该函数可以读取SD卡中的一个字节 * 使用范例:tempt=SD_Read_Byte();// 读取一个字节,并赋给tempt变量 ****************************************************************************/ unsigned char SD_Read_Byte() { unsigned char value=0; unsigned char temp=0; do{ //-----此处,调用底层G2硬件接口函数----- temp=SPI_RxFrame(&value,1); }while(temp==0); return value; } 未完待续。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 50
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- baomayou.com 版权所有 赣ICP备2024042794号-6
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务