IO口模拟spi主从机通讯例程
下面这两幅图是,关于SPI数据读取或发送的时序图。
1、 主机 io口模拟spi通讯例程
//**spi io 口初始化 **//
void SPI_init(void)
{
gpio_configure_fpin(SPI_MISO,IO_TYPE_INPUT);//配置成输入模式
gpio_configure_fpin(SPI_MOSI,IO_OUTPUT_1);//配置成输出模式
gpio_configure_fpin(SPI_SCK,IO_OUTPUT_1); //配置成输出模式
gpio_configure_fpin(SPI_CS,IO_OUTPUT_1); //配置成输出模式
clr_spi_GPIO(SPI_SCK);//拉低 SPI_SCK
set_spi_GPIO(SPI_CS);//拉高 SPI_SCK
clr_spi_GPIO(SPI_MOSI);//拉低 SPI_MOSI
}
//**主机spi读取一字节api**//
unsigned char SPI_ReadByte(void){
unsignedchar i,rByte=0;
clr_spi_GPIO(SPI_CS);
for(i=0;i<8;i++){
clr_spi_GPIO(SPI_SCK);//clr_spi_sck;
delay_us(3);
rByte<<=1;
if(MISO_is_status())//
//M16MISO---PB6
rByte|=1;
set_spi_GPIO(SPI_SCK);//set_spi_sck;
delay_us(3);
}
clr_spi_GPIO(SPI_SCK);
set_spi_GPIO(SPI_CS);
return rByte;
}
//** 读取miso 的电平 **//
char MISO_is_status(void)
{
if(red_spi_GPIO(SPI_MISO))//
return1;
else
return0;
}
//**主机spi写入一字节api**//
void SPI_WriteByte(unsigned charwByte){
unsigned char i;
clr_spi_GPIO(SPI_CS);
for(i=0;i<8;i++){
clr_spi_GPIO(SPI_SCK);//
delay_us(3);//
if(wByte&0x80){
set_spi_GPIO(SPI_MOSI);//
}
else{
clr_spi_GPIO(SPI_MOSI);//
}
wByte=wByte<<1;
set_spi_GPIO(SPI_SCK);//set_spi_sck;
delay_us(3);//
}
clr_spi_GPIO(SPI_SCK);
set_spi_GPIO(SPI_CS);
}
////////////////////////////////////////////////////////////////////////////////////
注意,我写的主从机的io口对接如下
主机io 从机io
SPI_MISO ------------------------- SPI_MISO
SPI_MOSI ---------------------------SPI_MOSI
SPI_SCK ---------------------------SPI_SCK
SPI_CS --------------------------SPI_CS
可能有的人对上面的io口对接的方式感到奇怪,请仔细看我对这几个io口做的初始化设置就可以明白。其实左边SPI_MOSI是为主机的数据输出,SPI_MISO 为主机的数据输入。
而右边是SPI_MOSI是为从机的数据输入,SPI_MISO 为从机的数据输出。这个输入输出的设置主要还是对io口的初始化的地方做设置。
/*************************************************************/
2、 从机 io口模拟spi通讯例程
//**从机spi io 口初始化 **//
void SPI_init(void)
{
gpio_configure_fpin(SPI_MISO,IO_OUTPUT_0); //配置成输出模式
gpio_configure_fpin(SPI_MOSI,IO_TYPE_INPUT); //配置成输入模式
gpio_configure_fpin(SPI_SCK,IO_TYPE_INPUT); //配置成输入模式
gpio_configure_fpin(SPI_CS,HFM_IO_TYPE_INPUT);//配置成输入模式
}
//**从机spi读取一字节api**//
unsigned char SlaveSPI_read(void)
{
unsignedchar i,rrbyte=0,rflag=0,SPICS_pin=0,SPISCK_pin=0;
SPICS_pin=red_spi_GPIO(SPI_CS);
SPISCK_pin=red_spi_GPIO(SPI_SCK);
if((!(red_spi_GPIO(SPI_CS))) ){
for(i=0;i<8;i++){
rflag=1;
while(!(red_spi_GPIO(SPI_SCK)) );
rrbyte=rrbyte<<1;
if(red_spi_GPIO(SPI_MOSI))
rrbyte|=1;
while((red_spi_GPIO(SPI_SCK)) );
}
while( !(red_spi_GPIO(SPI_CS)) );
}
if(rflag)
returnrrbyte;
else
return0;
}
//**从机spi写入一字节api**//
void SlaveSPI_write(unsigned char wByte)
{
unsignedchar i;
if((!(red_spi_GPIO(SPI_CS))) ){
for(i=0;i<8;i++){
while((red_spi_GPIO(SPI_SCK)) );
if(wByte&0x80){
set_spi_GPIO(SPI_MISO);}//set_spi_si;
else{
clr_spi_GPIO(SPI_MISO);} //clr_spi_si;
while(!(red_spi_GPIO(SPI_SCK)) );
wByte<<=1;
}
while( !(red_spi_GPIO(SPI_CS)) ); }
}
上面的主从机通讯,我在M3的MCU中已经测试通过的。相信大家看以上例程也明白,这段代码对在什么环境中跑没什么关系,只需要你对相应的MCU环境做好相应IO口初始化就可以了。
我写这个是因为看到网上没有对这方面主从机通讯有系统的整理的。对初学者,有较好的帮助。对大牛的话,请不要扔砖啊,扔鸡蛋啊,谢谢!
总结,写spi io口初始化,一定要仔细看时序,还有就是主从机间的IO口,一定要结对。本人刚开始就是在io口上接反了条线,读出数据老是变化不对,纠结了非常久,希望对后面的单片机的学习爱好者有所帮助。
转发请注明原创!http://blog.csdn.net/hwh20095000060