SPI驱动!S3C6410 SPI 裸机驱动
扫描二维码
随时随地手机看文章
刚刚写的SPI驱动,想移植到LINUX上面用来读写SD卡
只测试了发送,没有测试接收.
spi.c
/*************************************************************************************************************
*文件名:spi.c
*功能:S3C6410SPI底层驱动函数
*作者:陈鹏
*创建时间:2012年9月8日20:35
*最后修改时间:2012年9月8日
*详细:SPI始化,发送,接收,配置等
*使用的是手动控制片选,因为在实际使用过程中手动控制片选较为灵活,但是也有个问题,就是何时取消片选,应为数据写入到发送FIFO并
*不代表数据已经发送完成了,如果在数据没有发送完成之前取消了片选会导致数据传输错误,因此简单的方法就是在发送数据后加入一定
*的延时,让数据发送完成后取消片选
*************************************************************************************************************/
#include"system.h"
#include"spi.h"
#include"delay.h"
//SPI通道数量
#defineSPI_CH_N2
//SPI外设结构
constSPI_TypeDef*SPI_CH[SPI_CH_N]={SPI0,SPI1};
//默认模式1
//主设备模式,空闲时钟低电平,第一个时钟边沿有效(上升沿有效),使能发送接收,数据宽度8bit,关闭DMA,使能手动控制片选
constSPI_Config_TypeDefSPI_DEFAULT_01={0,0,0,1,1,8,0,0,0,0};
/*************************************************************************************************************************
*函数:voidSPI_SetSpeed(u8ch,u8Speed)
*功能:设置SPI速度
*参数:CH:SPI通道选择;Speed:SPI速度设置
*返回:无
*依赖:底层宏定义
*作者:cp1300@139.com
*时间:20121005
*最后修改时间:20121005
*说明:修改的时候注意SPI应该处于空闲或者无效状态,使用的时钟是PCLK
*SPI时钟输出=时钟源/(2×(预分频值+1))
*************************************************************************************************************************/
voidSPI_SetSpeed(u8ch,u8Speed)
{
SPI_TypeDef*SPI;
if(ch>=SPI_CH_N)
return;//通道号超出范围
SPI=(SPI_TypeDef*)SPI_CH[ch];//获取对应通道寄存器结构指针
SPI->CLKCFG=0;//清空设置并关闭时钟
SPI->CLKCFG=Speed;//设置预分频值
SPI->CLKCFG|=BIT8;//使能时钟
}
/*************************************************************************************************************************
*函数:u8SPI_Init(u8ch,SPI_Config_TypeDef*config,u8Speed)
*功能:SPI初始化
*参数:CH:SPI通道选择;config:配置结构指针;Speed:SPI速度设置
*返回:0:初始化成功;1:初始化失败
*依赖:底层宏定义
*作者:cp1300@139.com
*时间:20121005
*最后修改时间:20121005
*说明:无
*************************************************************************************************************************/
u8SPI_Init(u8ch,constSPI_Config_TypeDef*config,u8Speed)
{
u32chcfg=0;
u32modcfg=0;
u32slavecfg=0;
SPI_TypeDef*SPI;
if(ch>=SPI_CH_N)
return1;//通道号超出范围
SPI=(SPI_TypeDef*)SPI_CH[ch];//获取对应通道寄存器结构指针
SPI->CHCFG|=BIT5;//SPI软复位
Delay_US(10);//适当延时
switch(ch)
{
case0://通道0
{
Set_GateClk(PCLK_SPI0,ENABLE);//使能SPI0门控时钟
rGPCCON&=~0xfff;
rGPCCON|=0x222;//初始化SPI0MISOCLKMOSI相关IO
}break;
case1://通道1
{
Set_GateClk(PCLK_SPI1,ENABLE);//使能SPI1门控时钟
rGPCCON&=~(0xfff<<16);
rGPCCON|=(0x222<<16);//初始化SPI1MISOCLKMOSI相关IO
}break;
default:break;
}
SPI->CLKCFG&=~BIT8;//关闭SPI时钟
SPI->CHCFG=0;//清除设置并关闭SPI发送接收通道
if(config->EnSlave)//使能从设备模式
{
chcfg|=BIT4;
}
if(config->EnCPOH)//使能空闲时钟高电平
{
chcfg|=BIT3;
}
if(config->EnCPHB)//使能第二个时钟边沿有效
{
chcfg|=BIT2;
}
if(config->EnRx)//使能接收
{
chcfg|=BIT1;
}
if(config->EnTx)//使能发送
{
chcfg|=BIT0;
}
switch(config->SetTranSize)//设置传输数据位宽
{
case16:modcfg|=(1<<29);modcfg|=(1<<17);break;//半字
case32:modcfg|=(2<<29);modcfg|=(2<<17);break;//字
default:break;//字节
}