www.pudn.com > STM32_CH376-SPI.zip > spi_init.c, change:2014-01-07,size:9024b


#include "spi_init.h" 
#include "stm32f10x_spi.h" 
#include "usart.h" 
#include "delay.h"	  
///////////////////////////////////////////////////////////////////////////////// 
  
//以下是SPI模块的初始化代码,配置成主机模式					   
//SPI口初始化 
//这里针是对SPI2的初始化 
 
 
 
void SPI2_Init(void) 
{ 
 	GPIO_InitTypeDef GPIO_InitStructure; 
    SPI_InitTypeDef  SPI_InitStructure; 
 
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能  
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOE, ENABLE );//PORTE时钟使能  
	RCC_APB1PeriphClockCmd(	RCC_APB1Periph_SPI2,  ENABLE );//SPI2时钟使能 	 
  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB 
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //PB12推挽输出  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB 
 
 	GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB12/13/14/15输出高 
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //PE1推挽输出  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE 
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //PE2上拉输入 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE 
 
 
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//设置SPI工作模式:设置为主SPI 
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//设置SPI的数据大小:SPI发送接收8位帧结构 
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;		//串行同步时钟的空闲状态为高电平 
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	//串行同步时钟的第二个跳变沿(上升或下降)数据被采样 
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;		//定义波特率预分频的值:波特率预分频值为256 
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 
	SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRC值计算的多项式 
	SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 
  
	SPI_Cmd(SPI2, ENABLE); //使能SPI外设 
			  
  
 
}    
//SPI 速度设置函数 
//SpeedSet: 
//SPI_BaudRatePrescaler_2   2分频    
//SPI_BaudRatePrescaler_8   8分频    
//SPI_BaudRatePrescaler_16  16分频   
//SPI_BaudRatePrescaler_256 256分频  
   
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler) 
{ 
  	assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler)); 
	SPI2->CR1&=0XFFC7; 
	SPI2->CR1|=SPI_BaudRatePrescaler;	//设置SPI2速度  
	SPI_Cmd(SPI2,ENABLE);  
}  
 
 
//SPIx 读写一个字节 
//TxData:要写入的字节 
//返回值:读取到的字节 
u8 SPI2_ReadWriteByte(u8 TxData) 
{		 
			 	 
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); //检查指定的SPI标志位设置与否:发送缓存空标志位 
			   
	SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据 
 
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); //检查指定的SPI标志位设置与否:接受缓存非空标志位 
	  						     
	return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据					     
} 
 
 
 
/******************************************************************************* 
* 描      述      : 延时指定微秒时间,根据单片机主频调整,不精确. 
*******************************************************************************/ 
void mDelayuS( UINT8 us ) 
{ 
	while ( us -- ); 
} 
 
/******************************************************************************* 
* 描      述      : 延时指定毫秒时间,根据单片机主频调整,不精确 
*******************************************************************************/ 
void mDelaymS( UINT8 ms ) 
{ 
	while ( ms -- )  
	{ 
		mDelayuS( 250 ); 
		mDelayuS( 250 ); 
		mDelayuS( 250 ); 
		mDelayuS( 250 ); 
	} 
} 
 
 
/******************************************************************************* 
* 函  数  名      : CH376_PORT_INIT 
* 描      述      : 由于使用软件模拟SPI读写时序,所以进行初始化. 
*                   如果是硬件SPI接口,那么可使用mode3(CPOL=1&CPHA=1)或 
*                   mode0(CPOL=0&CPHA=0),CH376在时钟上升沿采样输入,下降沿输出,数 
*                   据位是高位在前. 
*******************************************************************************/ 
void	CH376_PORT_INIT( void ) 
{ 
   CH376_SPI_SCS = 1;  /* 禁止SPI片选 */ 
   CH376_INT_WIRE=1;   /* 默认为高电平,SPI模式3,也可以用SPI模式0,但模拟程序可能需稍做修改 */ 
/* 对于双向I/O引脚模拟SPI接口,那么必须在此设置SPI_SCS,SPI_SCK,SPI_SDI为输出方向, 
*  SPI_SDO为输入方向 */ 
} 
 
/******************************************************************************* 
* 函  数  名      : xEndCH376Cmd   结束命令. 
*******************************************************************************/ 
void	xEndCH376Cmd( void ) 
{  
	CH376_SPI_SCS = 1; 	/* SPI片选无效,结束CH376命令,仅用于SPI接口方式 */ 
} 
 
/******************************************************************************* 
SPI输出8个位数据.    * 发送: UINT8 d:要发送的数据. 
*******************************************************************************/ 
void	Spi376OutByte( UINT8 d ) 
{   
   SPI2_ReadWriteByte(d);	  
} 
 
UINT8	Spi376InByte( void ) 
{ 
/* 如果是硬件SPI接口,应该是先查询SPI状态寄存器以等待SPI字节传输完成,然后从SPI数据寄存器读出数据 */ 
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) ;   //RXEN=0 接收缓冲区为空						     
	return SPI_I2S_ReceiveData(SPI2);   //返回收到的数据	 
} 
 
/******************************************************************************* 
* 描      述      : 向CH376写  命令. 
* 输      入      : UINT8 mCmd:要发送的命令.  //这一块有毛病 
*******************************************************************************/ 
void	xWriteCH376Cmd( UINT8 mCmd ) 
{ 
	CH376_SPI_SCS = 1;    /* 防止之前未通过xEndCH376Cmd禁止SPI片选 */ 
	delay_us(3); 
/* 对于双向I/O引脚模拟SPI接口,那么必须确保已经设置SPI_SCS,SPI_SCK,SPI_SDI为输出 
*  方向,SPI_SDO为输入方向 */ 
	CH376_SPI_SCS = 0;      /* SPI片选有效 */ 
	delay_ms(10); 
	Spi376OutByte( mCmd );  /* 发出命令码 */ 
	 
    delay_us(2);/* 延时1.5uS确保读写周期大于1.5uS,或者用上面一行的状态查询代替 */ 
  
} 
 
 
/******************************************************************************* 
* 描      述      : 向CH376写   数据. 
* 输      入      : UINT8 mData: 
*                   要发送的数据. 
*******************************************************************************/ 
void	xWriteCH376Data( UINT8 mData ) 
{ 
	Spi376OutByte( mData ); 
	delay_us( 1 );	  /* 确保读写周期大于0.6uS */ 
	//mDelayuS(10 );   
} 
 
 
/******************************************************************************* 
* 函  数  名      : xReadCH376Data 
* 描      述      : 从CH376读数据. 
*******************************************************************************/ 
UINT8	xReadCH376Data( void ) 
{ 
	UINT8 i; 
	delay_us( 10 ); 
	//mDelayuS(10); 
	i = SPI2_ReadWriteByte( 0xFF );	  
	return( i ); 
} 
 
 
/******************************************************************************* 
* 描      述      : 查询CH376中断(INT#低电平). 
* 返      回      : FALSE:无中断.       TRUE:有中断. 
*******************************************************************************/ 
UINT8	Query376Interrupt( void ) 
{ 
	UINT8 i; 
	i = (CH376_INT_WIRE ? FALSE : TRUE ); 	/* 如果连接了CH376的中断引脚则直接查询中断引脚 */ 
	return( i );  
} 
 
/******************************************************************************* 
* 描      述      : 初始化CH376. 
* 返      回      : FALSE:无中断.  TRUE:有中断. 
*******************************************************************************/ 
UINT8	mInitCH376Host( void ) 
{ 
	UINT8	res;	 
 
	delay_ms(200); 
	CH376_PORT_INIT( );           /* 接口硬件初始化 */ 
	xWriteCH376Cmd( CMD11_CHECK_EXIST );    /* 测试单片机与CH376之间的通讯接口 */ 
	xWriteCH376Data( 0x55 ); 
	res = xReadCH376Data( ); 
	printf("res =%02x \n",(unsigned short)res); 
	xEndCH376Cmd( ); 
	if ( res != 0xAA ) return( ERR_USB_UNKNOWN );  /* 通讯接口不正常,可能原因有:接口连接异常,其它设备影响(片选不唯一),串口波特率,一直在复位,晶振不工作 */ 
	xWriteCH376Cmd( CMD11_SET_USB_MODE ); /* 设备USB工作模式 */ 
	xWriteCH376Data( 0x06 ); //06H=已启用的主机方式并且自动产生SOF包   
	mDelayuS( 20 ); 
	res = xReadCH376Data( ); 
	printf("res =%02x \n",(unsigned short)res); 
	xEndCH376Cmd( ); 
 
	if ( res == CMD_RET_SUCCESS )  //RES=51  命令操作成功 
	{ 
	    return( USB_INT_SUCCESS ); //USB事务或者传输操作成功  
	} 
	else  
	{ 
	    return( ERR_USB_UNKNOWN );/* 设置模式错误 */ 
	} 
} 
/************************************ End *************************************/