你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

c++封装类 SPI

[复制链接]
wecreate 发布时间:2019-8-20 18:11
f407vet6的, 需要其他我的封装类文件,如果有问题,请大家指证。
使用:
SPI spi(SPI1);硬件模式
或者 SPI spi(new PORT(GPIOA,9)......)软件模式

spi.W(0xff) 写
spi.R() 读



============spi.h

#ifndef __MYSPI__
#define __MYSPI__
#include <base.h>

class SPI {
        public:
                SPI();
                SPI(PORT *MOSI,PORT *MISO,PORT *SDCK,u8 mode=0,u16 sp=0);
                SPI(SPI_TypeDef* spino,u8 mode=0,u16 sp=SPI_BaudRatePrescaler_2,u8 remap=0);
                void setMode(u8);
                void setSpeed(u16);
                u8 W(u8=0xff);       
                u8 R();

                u16 speed;
                        SPI_InitTypeDef spiStruct;
        private :
                        void InitSoft(PORT*,PORT*,PORT*,u16,u8);
                        void InitHard(SPI_TypeDef*,u8,u8,u8 remap);
       
                        u8 SRW(u8=0xff);
                        u8 HRW(u8=0xff);
                        u8 Mode;
                        bool isSoft;
       
                        SPI_TypeDef* spi;
                        PORT *MOSI,*MISO,*SDCK;
                        uint32_t rccspi;
                        uint8_t afspi;
       
                        void Init();
};



#endif



=========spi.cpp

#include "spi.h"
#include "myfun.h"

SPI::SPI(){}

        SPI::SPI(PORT *MOSI,PORT *MISO,PORT *SDCK,u8 mode,u16 sp) {
                        InitSoft(MOSI,MISO,SDCK,sp,mode);
        }
       
        SPI::SPI(SPI_TypeDef* spino,u8 mode,u16 sp,u8 remap) {
                        InitHard(spino,sp,mode,remap);
        }
               
void SPI::InitSoft(PORT *_MOSI,PORT *_MISO,PORT *_sdck,u16 sp,u8 mode){
                isSoft=true;
                Mode=mode;
                speed=sp;
                MOSI=_MOSI,MISO=_MISO,SDCK=_sdck;
                //MISO->setMode(GPIO_Mode_IN_FLOATING);
       
                MISO->setMode(GPIO_Mode_IN);
                MOSI->setMode(GPIO_Mode_OUT);
                SDCK->setMode(GPIO_Mode_OUT);

                (mode & 0x2)? SDCK->High():SDCK->Low();
}

void SPI::InitHard(SPI_TypeDef* spino,u8 sp,u8 mode,u8 remap) {
                isSoft=false;
                Mode=mode;
                speed=sp;
                spi=spino;
               
               
       
                if (spi==SPI1) {
                                afspi=GPIO_AF_SPI1;
                                rccspi=RCC_APB2Periph_SPI1;
                                if (remap==0) {
                                        MOSI=new PORT(GPIOA,7,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOA,6,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOA,5,GPIO_Mode_AF);
                                } else {
                                        MOSI=new PORT(GPIOB,5,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOB,4,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOB,3,GPIO_Mode_AF);
                                }
                }
                if (spi==SPI2) {
                                afspi=GPIO_AF_SPI2;
                                rccspi=RCC_APB1Periph_SPI2;
                                if (remap==0) {
                                        MOSI=new PORT(GPIOB,15,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOB,14,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOB,10,GPIO_Mode_AF);
                                }
                                if (remap==1) {
                                        MOSI=new PORT(GPIOC,3,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOC,2,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOB,13,GPIO_Mode_AF);
                                }
                                if (remap==2) {
                                        MOSI=new PORT(GPIOI,3,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOI,2,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOD,3,GPIO_Mode_AF);
                                }
                }
               
                if (spi==SPI3) {
                                afspi=GPIO_AF_SPI3;
                                rccspi=RCC_APB1Periph_SPI3;
                                if (remap==0) {
                                        MOSI=new PORT(GPIOB,5,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOB,4,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOB,3,GPIO_Mode_AF);
                                }
                                if (remap==1) {
                                        MOSI=new PORT(GPIOC,12,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOC,11,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOC,10,GPIO_Mode_AF);
                                }
                }
                if (spi==SPI4) {
                                afspi=GPIO_AF_SPI4;
                                rccspi=RCC_APB2Periph_SPI4;
                                if (remap==0) {
                                        MOSI=new PORT(GPIOE,6,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOE,7,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOE,2,GPIO_Mode_AF);
                                }
                                if (remap==1) {
                                        MOSI=new PORT(GPIOE,14,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOE,13,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOE,12,GPIO_Mode_AF);
                                }
                }
                if (spi==SPI5) {
                                afspi=GPIO_AF_SPI5;
                                rccspi=RCC_APB2Periph_SPI5;
                                if (remap==0) {
                                        MOSI=new PORT(GPIOF,9,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOF,8,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOF,7,GPIO_Mode_AF);
                                }
                                if (remap==1) {
                                        MOSI=new PORT(GPIOF,11,GPIO_Mode_AF);
                                        MISO=new PORT(GPIOH,7,GPIO_Mode_AF);
                                        SDCK=new PORT(GPIOH,6,GPIO_Mode_AF);
                                }
                }
                if (spi==SPI6) {
                                afspi=GPIO_AF_SPI6;
                                rccspi=RCC_APB2Periph_SPI6;
                                MOSI=new PORT(GPIOG,14,GPIO_Mode_AF);
                                MISO=new PORT(GPIOG,12,GPIO_Mode_AF);
                                SDCK=new PORT(GPIOG,13,GPIO_Mode_AF);
                }

                Init();
}


void SPI::Init()
{         
  SPI_InitTypeDef  SPI_InitStructure;
       
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA<<SDCK->PortNo, ENABLE);//使能GPIOA时钟
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA<<MOSI->PortNo, ENABLE);//使能GPIOA时钟
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA<<MISO->PortNo, ENABLE);//使能GPIOA时钟
       

        if (spi==SPI2 || spi==SPI3) {
                        RCC_APB1PeriphClockCmd(rccspi, ENABLE);//使能SPI23时钟
        } else {
                        RCC_APB2PeriphClockCmd(rccspi, ENABLE);//使能SPI1时钟
        }

        GPIO_PinAFConfig(SDCK->GPIO,GPIO_PinSource0 +(SDCK->PinNo/2),afspi); //PB3复用为 SPI1
        GPIO_PinAFConfig(MOSI->GPIO,GPIO_PinSource0+(MOSI->PinNo/2),afspi); //PB4复用为 SPI1
        GPIO_PinAFConfig(MISO->GPIO,GPIO_PinSource0+(MISO->PinNo/2),afspi); //PB5复用为 SPI1

        //这里只针对SPI口初始化
        //RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);//复位SPI1
        //RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);//停止复位SPI1

        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 =Mode &0x2;// SPI_CPOL_High;                //串行同步时钟的空闲状态为高电平
        SPI_InitStructure.SPI_CPHA =Mode &0x1 ;// SPI_CPHA_2Edge;        //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler =speed;// SPI_BaudRatePrescaler_4;                //定义波特率预分频的值:波特率预分频值为256
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC值计算的多项式
        SPI_Init(spi, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

        SPI_Cmd(spi, ENABLE); //使能SPI外设


}   


u8 SPI::W(u8 d) {
                return isSoft?SRW(d):HRW(d);
}

u8 SPI::R() {
                return isSoft?SRW():HRW();
}


u8 SPI::HRW(u8 d) {

                u8 retry=0;                                        
        while (SPI_I2S_GetFlagStatus(spi, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
                {
                retry++;
                if(retry>200)return 0;
                }                          
        SPI_I2S_SendData(spi, d); //通过外设SPIx发送一个数据
        retry=0;

        while (SPI_I2S_GetFlagStatus(spi, SPI_I2S_FLAG_RXNE) == RESET)//检查指定的SPI标志位设置与否:接受缓存非空标志位
                {
                retry++;
                if(retry>200)return 0;
                }                                                              
        return SPI_I2S_ReceiveData(spi); //返回通过SPIx最近接收的数据       
}

void SPI::setMode(u8 mode) {
                if (isSoft) Mode=mode; else {
                                u16 r=spi->CR1 & 0xfffc;
                                spi->CR1=r | mode;
                }
}


void SPI::setSpeed(u16 sp) {
        if (isSoft) {
                        speed=sp;
        }else{
                        spi->CR1 &=0xffc7;
                        spi->CR1 |=sp;
                        SPI_Cmd(spi,ENABLE);
        }
}

u8 SPI::SRW(u8 d) {
        u8 i=8;
        u8 r=0;
         
        switch(Mode) {
                case 0: //CPOL=0 ,CPHA=0
                        while(i--) {
                                r<<=1;
                                if (MISO->Read()) r++;
                                (d & 0x80)? MOSI->High():MOSI->Low();
                                SDCK->High();
                                delay_nop(speed);
                                d<<=1;
                                SDCK->Low();
                                delay_nop(speed);
                        }
                        break;;
                case 2://CPOL=1,CPHA=0
                                while(i--) {
                                                r<<=1;
                                                if (MISO->Read()) r++;
                                                (d & 0x80) ?MOSI->High():MOSI->Low();
                                                SDCK->Low();
                                                d<<=1;
                                                SDCK->High();
                                }
                                break;
                case 1: //CPOL=0,CPHA=1
                                while(i--) {
                                                SDCK->High();
                                                r<<=1;
                                                if (MISO->Read()) r++;
                                                (d & 0x80) ?MOSI->High():MOSI->Low();
                                                SDCK->Low();
                                                d<<=1;
                                }
                                break;
                case 3: //CPOL=1,CPHA=1
                               
                                while(i--) {
                                                r<<=1;
                                                (d & 0x80)?MOSI->High():MOSI->Low();
                                                delay_nop(speed);       
                                                SDCK->Low();
                                                delay_nop(speed);
                                                SDCK->High();
                                                if (MISO->Read()) r++;
                                               
                                                d<<=1;
                                }
                                break;
                }
        return r;
}
收藏 评论3 发布时间:2019-8-20 18:11

举报

3个回答
一代睡神的崛起 回答时间:2019-8-21 08:36:23
学习了,用类和对象操作
一代睡神的崛起 回答时间:2019-8-21 09:54:54
你的SPI名称空间怎么不发出来啊
wecreate 回答时间:2019-8-27 18:23:17
我是复制的代码,没有设置名称空间。

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版