spi从机程序设计_spi从机程序代码详细介绍

spi(serial peripheral interface)串行外围设备接口。是一种全双工同步通信总线。本文为大家介绍两种spi从机程序。
stm32f407的spi主从机通信程序 #include “spi.h”
u8 spi_data[3];
void spi1_init(void)
{
gpio_inittypedef gpio_initstructure;
spi_inittypedef spi_initstructure;
rcc_ahb1periphclockcmd(rcc_ahb1periph_gpiob, enable);//使能gpiob时钟
rcc_apb2periphclockcmd(rcc_apb2periph_spi1, enable);//使能spi1时钟
//gpiofb3,4,5初始化设置
gpio_initstructure.gpio_pin = gpio_pin_3|gpio_pin_4|gpio_pin_5;//pb3~5复用功能输出
gpio_initstructure.gpio_mode = gpio_mode_af;//复用功能
gpio_initstructure.gpio_otype = gpio_otype_pp;//推挽输出
gpio_initstructure.gpio_speed = gpio_speed_100mhz;//100mhz
gpio_initstructure.gpio_pupd = gpio_pupd_down;//上拉
gpio_init(gpiob, &gpio_initstructure);//初始化
gpio_pinafconfig(gpiob,gpio_pinsource3,gpio_af_spi1); //pb3复用为 spi1
gpio_pinafconfig(gpiob,gpio_pinsource4,gpio_af_spi1); //pb4复用为 spi1
gpio_pinafconfig(gpiob,gpio_pinsource5,gpio_af_spi1); //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 = 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_4; //定义波特率预分频的值:波特率预分频值为256
spi_initstructure.spi_firstbit = spi_firstbit_msb; //指定数据传输从msb位还是lsb位开始:数据传输从msb位开始
spi_initstructure.spi_crcpolynomial = 7; //crc值计算的多项式
spi_init(spi1, &spi_initstructure); //根据spi_initstruct中指定的参数初始化外设spix寄存器
spi_cmd(spi1, enable); //使能spi外设
//spi1_readwritebyte(0xff);//启动传输
}
//spi1速度设置函数
//spi速度=fapb2/分频系数
//@ref spi_baudrate_prescaler:spi_baudrateprescaler_2~spi_baudrateprescaler_256
//fapb2时钟一般为84mhz:
void spi1_setspeed(u8 spi_baudrateprescaler)
{
assert_param(is_spi_baudrate_prescaler(spi_baudrateprescaler));//判断有效性
spi1-》cr1&=0xffc7;//位3-5清零,用来设置波特率
spi1-》cr1|=spi_baudrateprescaler; //设置spi1速度
spi_cmd(spi1,enable); //使能spi1
}
//spi1 读写一个字节
//txdata:要写入的字节
//返回值:读取到的字节
void spi1_writebyte(u8 txdata)
{
while (spi_i2s_getflagstatus(spi1, spi_i2s_flag_txe) == reset){}//等待发送区空
spi_i2s_senddata(spi1, txdata); //通过外设spix发送一个byte 数据
//while (spi_i2s_getflagstatus(spi1, spi_i2s_flag_rxne) == reset){} //等待接收完一个byte
//return spi_i2s_receivedata(spi1); //返回通过spix最近接收的数据
}
void spi2_init(void)
{
gpio_inittypedef gpio_initstructure;
spi_inittypedef spi_initstructure;
rcc_ahb1periphclockcmd(rcc_ahb1periph_gpiob, enable);//使能gpioa时钟
rcc_apb1periphclockcmd(rcc_apb1periph_spi2, enable); //使能spi1时钟
//gpiofb3,4,5初始化设置
gpio_initstructure.gpio_pin = gpio_pin_13|gpio_pin_14|gpio_pin_15;//pb3~5复用功能输出
gpio_initstructure.gpio_mode = gpio_mode_af;//复用功能
gpio_initstructure.gpio_otype = gpio_otype_pp;//推挽输出
gpio_initstructure.gpio_speed = gpio_speed_100mhz;//100mhz
gpio_initstructure.gpio_pupd = gpio_pupd_down;//上拉
gpio_init(gpiob, &gpio_initstructure);//初始化
gpio_pinafconfig(gpiob,gpio_pinsource13,gpio_af_spi2); //pb13复用为 spi2
gpio_pinafconfig(gpiob,gpio_pinsource14,gpio_af_spi2); //pb14复用为 spi2
gpio_pinafconfig(gpiob,gpio_pinsource15,gpio_af_spi2); //pb15复用为 spi2
//这里只针对spi口初始化
rcc_apb2periphresetcmd(rcc_apb1periph_spi2,enable);//复位spi1
rcc_apb2periphresetcmd(rcc_apb1periph_spi2,disable);//停止复位spi1
spi_initstructure.spi_direction = spi_direction_2lines_fullduplex; //设置spi单向或者双向的数据模式:spi设置为双线双向全双工
spi_initstructure.spi_mode = spi_mode_slave; //设置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_2; //定义波特率预分频的值:波特率预分频值为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外设
}
//spi1速度设置函数
//spi速度=fapb2/分频系数
//@ref spi_baudrate_prescaler:spi_baudrateprescaler_2~spi_baudrateprescaler_256
//fapb2时钟一般为84mhz:
void spi2_setspeed(u8 spi_baudrateprescaler)
{
assert_param(is_spi_baudrate_prescaler(spi_baudrateprescaler));//判断有效性
spi2-》cr1&=0xffc7;//位3-5清零,用来设置波特率
spi2-》cr1|=spi_baudrateprescaler; //设置spi2速度
spi_cmd(spi2,enable); //使能spi1
}
//spi2 读写一个字节
//txdata:要写入的字节
//返回值:读取到的字节
u8 spi2_readbyte()
{
//while (spi_i2s_getflagstatus(spi2, spi_i2s_flag_txe) == reset){}//等待发送区空
//spi_i2s_senddata(spi2, txdata); //通过外设spix发送一个byte 数据
while (spi_i2s_getflagstatus(spi2, spi_i2s_flag_rxne) == reset){} //等待接收完一个byte
return spi_i2s_receivedata(spi2); //返回通过spix最近接收的数据
}
void spi2_writebyte(u8 txdata)
{
spi_i2s_senddata(spi2, txdata); //通过外设spix发送一个byte 数据
while (spi_i2s_getflagstatus(spi2, spi_i2s_flag_txe) == reset){}//等待发送区空
}
//外部中断3服务程序
void exti3_irqhandler(void)
{
flage=flage|0x02;
cs2=0;
exti_clearitpendingbit(exti_line3); //清除line3上的中断标志位
}
//外部中断4服务程序
void exti4_irqhandler(void)
{
flage=flage|0x04;
cs3=0;
exti_clearitpendingbit(exti_line4); //清除line4上的中断标志位
}
//外部中断5服务程序
//外部中断初始化程序
void extix_init()
{
nvic_inittypedef nvic_initstructure;
exti_inittypedef exti_initstructure;
gpio_inittypedef gpio_initstructure;
rcc_apb2periphclockcmd(rcc_apb2periph_syscfg, enable);//使能syscfg时钟
rcc_ahb1periphclockcmd(rcc_ahb1periph_gpioe, enable); //使能gpioe时钟
gpio_initstructure.gpio_pin = gpio_pin_2|gpio_pin_3|gpio_pin_4|gpio_pin_5;
gpio_initstructure.gpio_mode = gpio_mode_in;//普通输入模式
gpio_initstructure.gpio_speed = gpio_speed_100mhz;//100m
gpio_initstructure.gpio_pupd = gpio_pupd_down;//上拉
gpio_init(gpioe, &gpio_initstructure);//初始化gpioe2,3,4,5
syscfg_extilineconfig(exti_portsourcegpioe, exti_pinsource2);//pe2 连接到中断线2
syscfg_extilineconfig(exti_portsourcegpioe, exti_pinsource3);//pe3 连接到中断线3
syscfg_extilineconfig(exti_portsourcegpioe, exti_pinsource4);//pe4 连接到中断线4
syscfg_extilineconfig(exti_portsourcegpioe, exti_pinsource5);//pe5 连接到中断线5
/* 配置exti_line2,3,4 */
exti_initstructure.exti_line = exti_line2 | exti_line3 | exti_line4 | exti_line5;
exti_initstructure.exti_mode = exti_mode_interrupt;//中断事件
exti_initstructure.exti_trigger = exti_trigger_rising; //下降沿触发
exti_initstructure.exti_linecmd = enable;//中断线使能
exti_init(&exti_initstructure);//配置
nvic_initstructure.nvic_irqchannel = exti2_irqn;//外部中断2
nvic_initstructure.nvic_irqchannelpreemptionpriority = 0x03;//抢占优先级3
nvic_initstructure.nvic_irqchannelsubpriority = 0x02;//子优先级2
nvic_initstructure.nvic_irqchannelcmd = enable;//使能外部中断通道
nvic_init(&nvic_initstructure);//配置
nvic_initstructure.nvic_irqchannel = exti3_irqn;//外部中断3
nvic_initstructure.nvic_irqchannelpreemptionpriority = 0x02;//抢占优先级2
nvic_initstructure.nvic_irqchannelsubpriority = 0x02;//子优先级2
nvic_initstructure.nvic_irqchannelcmd = enable;//使能外部中断通道
nvic_init(&nvic_initstructure);//配置
nvic_initstructure.nvic_irqchannel = exti4_irqn;//外部中断4
nvic_initstructure.nvic_irqchannelpreemptionpriority = 0x01;//抢占优先级1
nvic_initstructure.nvic_irqchannelsubpriority = 0x02;//子优先级2
nvic_initstructure.nvic_irqchannelcmd = enable;//使能外部中断通道
nvic_init(&nvic_initstructure);//配置
nvic_initstructure.nvic_irqchannel = exti9_5_irqn;//外部中断4
nvic_initstructure.nvic_irqchannelpreemptionpriority = 0x01;//抢占优先级1
nvic_initstructure.nvic_irqchannelsubpriority = 0x02;//子优先级2
nvic_initstructure.nvic_irqchannelcmd = enable;//使能外部中断通道
nvic_init(&nvic_initstructure);//配置
}
int main(void)
{
nvic_prioritygroupconfig(nvic_prioritygroup_2);//设置系统中断优先级分组2
delay_init(100); //初始化延时函数
led_init(); //初始化led
cs_init();
spi1_init();
spi2_init();
extix_init();
while(1)
{
cs2=1;
if(flage&0x02)
{
flage=flage&0xfd;
cs3=1;
}
if(flage&0x04)
{
flage=flage&0xfb;
spi1_writebyte(0xaa);
spi_data[0]=spi2_readbyte();
spi1_writebyte(0xc3);
spi_data[1]=spi2_readbyte();
spi1_writebyte(0x55);
spi_data[2]=spi2_readbyte();
if((spi_data[0]==0xaa)&&(spi_data[1]==0xc3)&&(spi_data[2]==0x55))
{
beep=~beep;
led0=~led0;
led1=~led1;
delay_ms(500);
}
memset(spi_data,0,3);
}
}
}
基于计数器的spi从机程序设计 spi 即为:serial peripheral interface,串行外围设备接口。是一种全双工同步通信总线。通信是通过数据传输来完成的,spi是串行通信协议,也就是说,数据时一位一位传输的。也就是时钟线存在的原因,由于时钟线提供的时钟脉冲,数据发送和数据接收都是基于这个时钟脉冲完成数据传输的,数据通过数据输出线输出,数据在时钟上升沿或者下降沿时改变,在紧接着的下降沿或者上升沿被读取,完成一次数据传输,输入原理和输出一样。也就是说数据输入和输出是在同一个时钟完成的,而区别就是在时钟的上升沿输入那么在时钟下降沿就输出,或者相反。为了实现这一点,一下设计就是通过一个计数器,在计数器数到偶数的时候则输出,计数器数到奇数的时候则输入。代码如下:

MAX4983E, MAX4984E 高速USB 2.0开关
如何使用Arduino创建摩尔斯电码生成器
明年显示产业投资将“V字反弹”,大涨74%
一位通信工程师年终总结居然是这样
MicroLED合资公司Luumii LED灯解决方案现进入量产阶段
spi从机程序设计_spi从机程序代码详细介绍
高交会直击:玩转智能终端科技路线
5G之路,承载先行!华为推动FlexE 2.0标准
复锦功率半导体电源模块产品发布会成功举办
有极继电器的特点和工作原理
can总线的数据帧中数据长度码和数据字节数的关系?
朗逸LED大灯测试
采用GR64模块的通用GPRS数传单元设计方案
荣耀20i采用了麒麟710处理器最高支持6GB+256GB存储和512GB存储卡拓展
5个导致PCB故障的常见错误
想让安防系统变得更稳定可靠吗?你只差一个低功耗无线模块
华为Mate Xs预约人数已超过14.7万人 国行售价依然保持16999元
一文解析MEC技术与移动网络重构
普渡机器人引领餐饮行业走向智慧发展新时代
第四届40人智能照明论坛7月31日深圳圆满落幕