SPI
/* * @Description : SPI(串行同步全双工) * @Author : wangxy * @Date : 2020-12-04 13:30:00 * @LastEditTime: Today * @LastEditors : wangxy * @FilePath : SPI.c * **/ //选择协议模式 #define SPI_CPOL 1 //时钟极性 0:时钟空闲低电平 1:时钟空闲高电平 #define SPI_CPHA 0 //时钟相位 0:第一个跳变沿接收; 第二个跳变沿发送 1:第二个跳变沿接收; 第一个跳变沿发送 //设置IO引脚 #define CLOK_PIN PD_ODR_ODR6 //时钟引脚 #define MOSI_PIN PD_ODR_ODR6 //输出引脚 #define MISO_PIN PD_IDR_IDR5 //输入引脚 #define NCSS_PIN PD_ODR_ODR7 //片选引脚 //====================================================== //* @description: SPI初始化 //* @param : NULL //* @return : NULL //====================================================== void SPI_Init(void) { NCSS_PIN =0; #if SPI_CPOL==0 && SPI_CPHA==0 //模式0:时钟空闲低电平 - 第一个跳变沿接收; 第二个跳变沿发送 CLOK_PIN =0; #endif #if SPI_CPOL==0 && SPI_CPHA==1 //模式1:时钟空闲低电平 - 第二个跳变沿接收; 第一个跳变沿发送 CLOK_PIN =0; #endif #if SPI_CPOL==1 && SPI_CPHA==0 //模式2:时钟空闲高电平 - 第一个跳变沿接收; 第二个跳变沿发送 CLOK_PIN =1; #endif #if SPI_CPOL==1 && SPI_CPHA==1 //模式3:时钟空闲高电平 - 第二个跳变沿接收; 第一个跳变沿发送 CLOK_PIN =1; #endif } //====================================================== //* @description: SPI_MODE1_WRITE //* @param : #Spi_Sed_Data 写一个数据 //* @return : NULL //====================================================== void SPI_Write(u8 Spi_Sed_Data) { u8 n =0; #if SPI_CPOL==0 && SPI_CPHA==0 //模式0:时钟空闲低电平 - 第一个跳变沿接收; 第二个跳变沿发送 for(n=0;n<8;n++){ SCK_D(1); if(Spi_Sed_Data&0x80) MOSI_D(1); else MOSI_D(0); Spi_Sed_Data<<=1; SCK_D(0); } SCK_D(0); //CLOK空闲低 #endif #if SPI_CPOL==0 && SPI_CPHA==1 //模式1:时钟空闲低电平 - 第二个跳变沿接收; 第一个跳变沿发送 for(n=0;n<8;n++){ SCK_D(0); if(Spi_Sed_Data&0x80) MOSI_D(1); else MOSI_D(0); Spi_Sed_Data<<=1; SCK_D(1); } SCK_D(0); //CLOK空闲低 #endif #if SPI_CPOL==1 && SPI_CPHA==0 //模式2:时钟空闲高电平 - 第一个跳变沿接收; 第二个跳变沿发送 for(n=0;n<8;n++){ SCK_D(0); if(Spi_Sed_Data&0x80) MOSI_D(1); else MOSI_D(0); Spi_Sed_Data<<=1; SCK_D(1); } SCK_D(1); //CLOK空闲高 #endif #if SPI_CPOL==1 && SPI_CPHA==1 //模式3:时钟空闲高电平 - 第二个跳变沿接收; 第一个跳变沿发送 for(n=0;n<8;n++){ SCK_D(1); if(Spi_Sed_Data&0x80) MOSI_D(0); else MOSI_D(1); Spi_Sed_Data<<=1; SCK_D(0); } SCK_D(1); //CLOK空闲高 #endif } //====================================================== //* @description: SPI_MODE1_READ //* @param : NULL //* @return : #Spi_Rcv_Data 读一个数据 //====================================================== u8 SPI_Read(void) { u8 n =0; u8 Spi_Rcv_Data =0; #if SPI_CPOL==0 && SPI_CPHA==0 //模式0:时钟空闲低电平 - 第一个跳变沿接收; 第二个跳变沿发送 for(n=0;n<8;n++){ Spi_Rcv_Data <<1; SCK_D(0); if(MISO_PIN) Spi_Rcv_Data |=1; else Spi_Rcv_Data &=0xfe; SCK_D(1); } SCK_D(0); //CLOK空闲低 #endif #if SPI_CPOL==0 && SPI_CPHA==1 //模式1:时钟空闲低电平 - 第二个跳变沿接收; 第一个跳变沿发送 for(n=0;n<8;n++){ Spi_Rcv_Data <<1; SCK_D(1); if(MISO_PIN) Spi_Rcv_Data |=1; else Spi_Rcv_Data &=0xfe; SCK_D(0); } SCK_D(0); //CLOK空闲低 #endif #if SPI_CPOL==1 && SPI_CPHA==0 //模式2:时钟空闲高电平 - 第一个跳变沿接收; 第二个跳变沿发送 for(n=0;n<8;n++){ Spi_Rcv_Data <<1; SCK_D(1); if(MISO_PIN) Spi_Rcv_Data |=1; else Spi_Rcv_Data &=0xfe; SCK_D(0); } SCK_D(1); //CLOK空闲高 #endif #if SPI_CPOL==1 && SPI_CPHA==1 //模式3:时钟空闲高电平 - 第二个跳变沿接收; 第一个跳变沿发送 for(n=0;n<8;n++){ Spi_Rcv_Data <<1; SCK_D(0); if(MISO_PIN) Spi_Rcv_Data |=1; else Spi_Rcv_Data &=0xfe; SCK_D(1); } SCK_D(1); //CLOK空闲高 #endif return Spi_Rcv_Data; } //====================================================== //* @description: 主函数 //* @param : NULL //* @return : NULL //====================================================== void main(void) { SPI_Init(); while(1){ u8 SPI_Rcv_Data =0; NCSS_PIN =0; //片选设备 SPI_Write(0xff); //写入数据 SPI_Rcv_Data =SPI_Read(); printf("SPI_Rcv_Data = %d\t\n",SPI_Rcv_Data); NCSS_PIN =1; //取消片选 } }
Stay hungry, stay foolish
待续。。。

浙公网安备 33010602011771号