找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 26048|回复: 8
收起左侧

STM8L的SPI1基本读写方法详解 含例程

  [复制链接]
ID:140343 发表于 2016-10-10 00:53 | 显示全部楼层 |阅读模式
STM8L的硬件SPI1共有三个主要引脚,分别是MOSI,MISO,SCK。NSS引脚只有在SMT8L作为从设备时,才有用,用于判断是否被选择与SPI主设备通信。本文选取NRF24L01作为SPI从设备,STM8L作为主设备,进行SPI读写功能测试。

下图是淘宝上可以买到的最常见的NRF24L01模块引脚图,可以看到除了MOSI,MISO,SCK,三个和SPI1硬件有关的引脚外,还有CE,CSN,IRQ这三个引脚,这三个引脚用STM8L的普通IO驱动即可.

从下图可以看到,CSN为芯片的使能引脚,读写寄存器时CSN必须为低电平.CE配合的内部配置寄存器,决定NRF24L01状态.

本例中,STM8L作为SPI主设备,在STM8L用户手册关于SPI作为主设备的详细配置流程如下图.


本文只是简单的测试SPI的读写功能,通过标志位等待实现硬件SPI读写单个字节.没有使用中断和DMA功能.
注意:向NRF24L01写数据时,需要在寄存器地址加上0x20,用于指示下一字节发送的数据是写入这个寄存器的.
下图是实际调试结果截图,查看NRF24L01的数据手册,可以知道0x00,0x01,0x02这三个寄存器的复位值分别为0x08,0x3F,0x03.由于0x00这个寄存器中的数据被我改写过了,所以这里显示改写值0x55.

  1. /*硬件连接*

  2. //    STM8L          NRF24L01

  3. //    PB4     -->      CSN

  4. //    PD4     -->      CE

  5. //    PB5     -->      SCK

  6. //    PB6     -->      MOSI

  7. //    PB7     <--      MISO

  8. /****************************************************************************************

  9. *开发环境:IAR for stm8 v1.40.1

  10. *硬件平台:STM8L-DISCOVERY

  11. *功能说明:通过硬件SPI等待的方法,实现对NRF24L01寄存器的读写,借助IAR软件的调试功能,查看变量的数值

  12. *作    者:茗风

  13. ****************************************************************************************/

  14. #include"iostm8l152c6.h"

  15. #include"stdbool.h"

  16. #include"stdint.h"

  17.   

  18. #define CSN_H           PB_ODR_ODR4=1

  19. #define CSN_L                  PB_ODR_ODR4=0

  20. #define CE_H            PD_ODR_ODR4=1

  21. #define CE_L            PD_ODR_ODR4=0

  22. uint16_t VDD_Value=0;

  23. /******************************************************************************************************

  24. *  名    称:void delay_10ms(uint8_t x_ms)

  25. *  功    能:延时10ms

  26. *  入口参数:无

  27. *  出口参数:无

  28. *  说    明:

  29. *  范    例:无

  30. ******************************************************************************************************/

  31. void delay_100ms(void)

  32. {

  33.   uint8_t i,j;

  34.   for(i=0;i<255;i++)//2*255个指令周期

  35.     for(j=0;j<255;j++);//2*255个指令周期

  36.   //delay_10ms共消耗 x_ms*2*255+2*x_ms个指令周期  

  37.   //255*2*255+2*255=130610us=130ms

  38.   //此延时函数,延时时间为130ms

  39.   //16M/8/2=1M 一个指令周期为1us

  40. }


  41. ///******************************************************************** **********************************

  42. //*  功  能   :SPI基本写一个字节函数

  43. //*  入口参数   :address为寄存器地址

  44. //            data为写入数据

  45. //*  出口参数   :无

  46. //*  说  明   :SPI文件提供基本的写函数,具体的器件写方式可能不同,建议使用基本函数进行封装

  47. //*  范  例   :无

  48. //******************************************************************************************************/

  49. void SPI1_Write_REG(uint8_t address,uint8_t data)

  50. {

  51.     uint8_t tmp;

  52.     address |=0x20;

  53.     CSN_L;

  54.     SPI1_DR=address;//写入需要操作的寄存器地址,

  55.     while(!(SPI1_SR_RXNE));

  56.     tmp=SPI1_DR;   //读取数据,仅仅是为了清除标志位

  57.     while(!(SPI1_SR_TXE));//等待发送寄存器为空

  58.     SPI1_DR=data;

  59.     while(!(SPI1_SR_TXE));

  60.     CSN_H;

  61. }


  62. ///******************************************************************** **********************************

  63. //*  功  能        :SPI基本读一个字节函数

  64. //*  入口参数        :address为寄存器地址

  65. //*  出口参数        :无

  66. //*  说  明        :SPI文件提供基本的读函数,具体的器件读方式可能不同,建议使用基本函数进行封装

  67. //*  范  例        :无

  68. //******************************************************************************************************/

  69. uint8_t SPI1_Read_REG(uint8_t address)

  70. {

  71.   volatile uint8_t value=0;

  72.   CSN_L;

  73.   value=SPI1_DR;//读一次,清除标志位

  74.   while(!(SPI1_SR_TXE));

  75.   SPI1_DR=address;//写入需要操作的寄存器地址,

  76.   

  77.   while(!(SPI1_SR_RXNE));

  78.   value=SPI1_DR;

  79.   

  80.   while(!(SPI1_SR_TXE));

  81.   SPI1_DR=0xFF;//写入一个无效值

  82.   

  83.   while(!(SPI1_SR_RXNE));//准备读数据

  84.   value=SPI1_DR;

  85.   CSN_H;

  86.   return value;

  87. }

  88. /******************************************************************************************************

  89. * 名 称: SPI_init()

  90. * 功 能:初始化SPI

  91. * 入口参数:无

  92. * 出口参数:无

  93. * 说 明: SP1传输速率设置为fmaster/2=8M,主模式,

  94. * 范 例:无

  95. ******************************************************************************************************/

  96. void SPI_Init(void)

  97. {

  98.   static uint8_t temp0=0,temp1=0,temp2=0,temp3=0;

  99. //输出IO

  100.   PD_DDR_DDR4 =1;//CE设置为输出

  101.   PB_DDR_DDR4 =1;//CSN设置为输出

  102.   PB_DDR_DDR5 =1;//SCK设置为输出

  103.   PB_DDR_DDR6 =1;//SIMO设置为输出

  104.   

  105.   PD_CR1_C14 =1;//CE设置为推挽输出

  106.   PB_CR1_C14 =1;//CSN设置为推挽输出

  107.   PB_CR1_C15 =1;//SCK设置为推挽输出

  108.   PB_CR1_C16 =1;//SIMO设置为推挽输出

  109.   

  110.   PB_CR2_C26 =1;//SIMO的IO输出速率为10MHz

  111.   PB_CR2_C25 =1;//SCK的IO输出速率为10MHz

  112.   PD_CR2_C24 =1;//CE的IO输出速率为10MHz

  113.   PB_CR2_C24 =1;//CSN的IO输出速率为10MHz

  114.   

  115. //输入IO

  116.   PD_DDR_DDR5 =0;//IRQ设置为输入

  117.   PB_DDR_DDR7 =0;//SOMI设置为输入

  118.   

  119.   PD_CR1_C15 =1;//IRQ设置为带上拉电阻输入

  120.   PB_CR1_C17 =1;//SOMI设置带上拉电阻输入

  121.   

  122.   PD_CR2_C25 =0;//关闭IRQ中断

  123.   PB_CR2_C27 =0;//关闭中断



  124.   

  125.   CLK_PCKENR1_PCKEN14=1;//打开SPI1外设时钟

  126.   

  127.   SPI1_CR1_SPE=0;//关闭SPI设备

  128.   //设置串行波特率

  129.   SPI1_CR1_BR=0;//fmaster/2=1M

  130.   

  131.   //配置CPOL和CPHA,定义数据传输和串行时钟间的相位关系

  132.   SPI1_CR1_CPHA=0;//数据采样从第一个时钟边沿开始

  133.   SPI1_CR1_CPOL=0;//空闲状态时,SCK保持低电平  

  134.   

  135.    //定义帧格式

  136.   SPI1_CR1_LSBFIRST=0;//先发送MSB

  137.   

  138.     //使能从设备管理//主模式需通过改变SSI位 来控制SPI_SEL

  139.   SPI1_CR2_SSM=1;//禁止软件从设备

  140.   SPI1_CR2_SSI=1;

  141.   

  142.   //主从设备模式选择

  143.   SPI1_CR1_MSTR=1;//作为主设备

  144.   

  145.   SPI1_CR2_RXONLY=0;//全双工

  146.   SPI1_CR2_BDM=0;//选择单向数据模式

  147.   

  148.   SPI1_CR1_SPE=1;//开启SPI设备

  149.   

  150. //NRF24L01上电复位后需要100ms才能进入到掉电模式

  151. //配置NRF24L01之前必须要有100ms以上的延时

  152.   delay_100ms();

  153.   //至此NRF24L01进入到掉电模式,允许对NRF24L01寄存器进行读写操作

  154.   CE_L;

  155.   CSN_H;

  156.   PB_DDR_DDR5=0;//SCK_L

  157.   

  158. /************以下,几个读写操作,是为了测试SPI读写功能*****************/  

  159.   temp0=SPI1_Read_REG(0x00);//

  160.   temp1=SPI1_Read_REG(0x01);//0x3F

  161.   temp2=SPI1_Read_REG(0x02);//0x03



  162.   SPI1_Write_REG(0x00,0x38);

  163.   temp3=SPI1_Read_REG(0x00);

  164.   asm("nop");

  165. }

  166. void main(void)

  167. {

  168.   SPI_Init();

  169. //  asm("rim");               //enable interrupts

  170.   while(1)

  171.   {

  172.     asm("wfi");

  173.   }

  174. }
复制代码




评分

参与人数 1黑币 +5 收起 理由
QWEFXSDFB + 5

查看全部评分

回复

使用道具 举报

ID:237191 发表于 2017-10-4 00:38 | 显示全部楼层
炒鸡感谢,原来STM8L的SPI要将MISO口设为输入,明明STM32都是设置复用输出的,STM8S根本不需要配置IO口,坑爹啊,困扰一天的BUG终于解决了,多谢!!!
回复

使用道具 举报

ID:281021 发表于 2018-4-12 08:58 | 显示全部楼层
谢谢分享,超级有用!
回复

使用道具 举报

ID:203038 发表于 2018-4-27 23:10 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:277370 发表于 2018-9-18 11:32 | 显示全部楼层
刚刚要学习这块芯片。。。学习学习啦。。
回复

使用道具 举报

ID:18591 发表于 2019-2-28 23:30 | 显示全部楼层
不錯~~~~~~~~~~~~~~~~
回复

使用道具 举报

ID:622341 发表于 2019-10-11 15:51 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:342258 发表于 2019-11-19 22:43 | 显示全部楼层
多谢!好人一生平安!
回复

使用道具 举报

ID:1023716 发表于 2023-8-22 01:53 | 显示全部楼层
這個例程比較好,幾乎所有的語句都有注釋。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表