您好,欢迎来到宝玛科技网。
搜索
您的当前位置:首页基于MSP430F5529的MP3

基于MSP430F5529的MP3

来源:宝玛科技网


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 #include\"font.h\"

/*****************************************************************************************

* 函数名称: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;nfor(i=0;i{

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((10if((KEY_Past==1)&&(KEY_Now==0)) //前一次高电平、后一次低电平,说明

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((10if((KEY_Past==1)&&(KEY_Now==0)) //前一次高电平、后一次低电平,说明按键按下

{

//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;iSD_Write_Byte(SD_EMPTY_CLK); }

//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//-----空读(放弃存储)其他字节----- SD_Read_Byte(); }

//超时判断

//超时判断

//超时门

//超

//超时门

//超

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

本站由北京市万商天勤律师事务所王兴未律师提供法律服务