[STM8] STM8L151K4的SPI通信

[复制链接]
 楼主| 13714765431 发表于 2015-12-24 18:45 | 显示全部楼层 |阅读模式
各位大师,刚学STM8L151K4芯片,不熟,不知有没有成熟的SPI通信实例(IAR工程),请大师支援,谢谢。
米尔豪斯 发表于 2015-12-24 19:59 | 显示全部楼层
STM8L151K4芯片有内部SPI资源吗,也可以模拟SPI
mintspring 发表于 2015-12-24 21:56 | 显示全部楼层
天灵灵地灵灵 发表于 2015-12-24 22:12 | 显示全部楼层
stm32 SPI通信[操作寄存器+库函数]
作者:Changing发表时间:07-14 17:57分类:电子相关4 Comments
前一篇:stm32 can总线通信[库函数]
后一篇:Uip + Stm32移植问题总结
    SPI(Serial Peripheral Interface--串行外设接口) 总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。 SPI是Freescale(原 Motorola)公司首先在其处理器上定义的。
    SPI是一种高速、主从式、全双工、同步传输的通信总线,SPI总线在物理层体现为四根传输线:
MOSI (Master Output Slaver Input) – 主器件数据输出,从器件数据输入
MISO (Master Input Slaver Output)  – 主器件数据输入,从器件数据输出
SCLK – 时钟信号,由主器件产生
NSS – 从器件使能信号,由主器件控制,有的IC会标注为CS(Chip select)
    CS线用于控制片选信号,当一个SPI从设备的CS线识别到了预先规定的片选电平,则该设备被选中。显然可以通过CS线,完成“一主多从”的SPI网络架设,在进行“一主一从”的SPI通信时,SPI并不是必须的。

    SPI总线传输数据时,由主机的SCLK线提供时钟脉冲,从机被动的接收时钟脉冲。主机在数据发送前,将数据写入数据寄存器,等待时钟脉冲移位输出,每个脉冲周期传输1位数据。 从机在主机的数据发送中,依靠主机的时钟,将从机的数据寄存器内容移位发送。所以要实现主从数据交换,在时钟信号前,主机 从机都必须先将数据写入数据寄存器,并且从机必须在主机前写入,然后由主机的SCLK时钟驱动发送。 不注意这个问题很容易造成SPI接收的数据错位。

    这样的全双工、同步传输完全依赖于 主机控制的时钟线SCLK,而且SCLK上只有数据传输的时候才有时钟信号。主机向从机发送数据不会有问题,但是如果从机主动向主机发送数据呢?
    从机要发送数据,必须要有SCLK的时钟,所以只能主机发送一个DUMMY(哑巴)字节,产生时钟,来实现和从机的数据交换。 从设备只能被动发送数据,无法主动发送数据。

    本例实现 通过将STM32上的2个SPI接口对接,进行一个简单的数据交换。使用SPI1作为主设备,SPI2作为从设备,通过串口查看数据通信的情况。

天灵灵地灵灵 发表于 2015-12-24 22:14 | 显示全部楼层
直接操作寄存器

首先配置SPI主机的频率
SPI1设备属于高速设备,隶属APB2总线,最大时钟72Mhz;
SPI2属于低速设备,隶属APB1总线,最大36Mhz。

在控制寄存器中设置时钟分频值,设置时钟极性和相位等。程序中有注释,详见代码:

User/main.c  (system.h 和 stm32f10x_it.h 等相关代码参照 stm32 直接操作寄存器开发环境配置)
  1. #include <stm32f10x_lib.h>       
  2. #include "system.h"
  3. #include "usart.h"
  4. #include "spi.h"

  5. #define LED1 PAout(4)
  6. #define LED2 PAout(5)
  7. #define LED3 PAout(6)
  8. #define LED4 PAout(7)


  9. void Gpio_Init(void);

  10. #define BufferSize 32

  11. u8 SPI1_Buffer_Tx[BufferSize] =            
  12. {
  13.     0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
  14.     0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,
  15.     0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
  16.     0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20
  17. };


  18. u8 SPI2_Buffer_Tx[BufferSize] =            
  19. {
  20.     0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,
  21.     0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,
  22.     0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,
  23.     0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70
  24. };

  25. u8 SPI1_Buffer_Rx[BufferSize] = {0xFF};
  26. u8 SPI2_Buffer_Rx[BufferSize] = {0xFF};
  27. u8 Tx_Counter = 0;
  28. u8 Rx_Counter = 0;


  29. int main(void)
  30. {       
  31.           u8 k=0;

  32.         Rcc_Init(9);                                                    //系统时钟设置

  33.         Usart1_Init(72,9600);

  34.         Nvic_Init(1,0,SPI1_IRQChannel,4);          //设置抢占优先级为1,响应优先级为0,中断分组为4
  35.         Nvic_Init(1,1,SPI2_IRQChannel,4);          //设置抢占优先级为1,响应优先级为1,中断分组为4

  36.         Gpio_Init();

  37.         Spi_Init(SPI1);
  38.         Spi_Init(SPI2);


  39.         while(Tx_Counter < BufferSize)
  40.         {       

  41.                 Spi_Write(SPI2,SPI2_Buffer_Tx[Tx_Counter]);                        //必须先将从设备数据写入数据寄存器,等待时钟同步

  42.                 Spi_Write(SPI1,SPI1_Buffer_Tx[Tx_Counter]);                          //主设备将数据写入数据寄存器,触发同步时钟,让主从数据寄存器由此时钟发送
  43.                
  44.                 SPI2_Buffer_Rx[Rx_Counter] = Spi_Read(SPI2);

  45.                 SPI1_Buffer_Rx[Rx_Counter] = Spi_Read(SPI1);       

  46.             Tx_Counter++;
  47.                 Rx_Counter++;

  48.         }       

  49.         printf("\r\n The SPI1 has sended data below : \r\n");

  50.         while(k<BufferSize)
  51.         {
  52.                 printf(" %0.2d \r ",SPI1_Buffer_Tx[k]);
  53.                 k++;
  54.         }

  55.         printf("\r\n The SPI2 has received data below : \r\n");

  56.         k=0;

  57.         while(k<BufferSize)
  58.         {
  59.                 printf(" %0.2d \r ",SPI2_Buffer_Rx[k]);
  60.                 k++;
  61.         }

  62.         k=0;

  63.         printf("\r\n The SPI2 has sended data below : \r\n");
  64.                                                                           
  65.         while(k<BufferSize)
  66.         {
  67.                 printf(" %0.2d \r ",SPI2_Buffer_Tx[k]);
  68.                 k++;
  69.         }

  70.         printf("\r\n The SPI1 has received data below : \r\n");

  71.         k=0;

  72.         while(k<BufferSize)
  73.         {
  74.                 printf(" %0.2d \r ",SPI1_Buffer_Rx[k]);
  75.                 k++;
  76.         }         

  77.         while(1);               
  78. }


  79. void Gpio_Init(void)
  80. {
  81.         RCC->APB2ENR |= 1<<2;                    //使能PORTA时钟        
  82.         RCC->APB2ENR |= 1<<3;                    //使能PORTB时钟;        


  83.         //SPI1 I/O设置

  84.         GPIOA->CRL &= 0x000FFFFF;                 //PA 5,6,7 复用  
  85.         GPIOA->CRL |= 0xBBB00000;

  86.         //SPI2 I/O设置

  87.         GPIOB->CRH &= 0x000FFFFF;                 //PB 13,14,15 复用  
  88.         GPIOB->CRH |= 0xBBB00000;

  89.        
  90.         //USART1 串口I/O设置

  91.         GPIOA -> CRH &= 0xFFFFF00F;           //设置USART1 的Tx(PA.9)为第二功能推挽,50MHz;Rx(PA.10)为浮空输入
  92.         GPIOA -> CRH |= 0x000008B0;          

  93. }
User/stm32f10x_it.c
  1. #include "stm32f10x_it.h"
  2. #include "system.h"
  3. #include "stdio.h"

  4. #define LED1 PAout(4)
  5. #define LED2 PAout(5)
  6. #define LED3 PAout(6)
  7. #define LED4 PAout(7)


  8. void SPI1_IRQHandler()
  9. {
  10.         if(SPI1->SR & 1<<7)                //SPI正忙于通信,或者发送缓冲非空
  11.         {
  12.                 printf("SPI1 is Busy");
  13.         }

  14.         if(SPI1->SR & 1<<6)                // 出现溢出错误
  15.         {
  16.                 printf("SPI1 is Overrun");
  17.         }

  18.         if(SPI1->SR & 1<<5)                //出现模式错误
  19.         {
  20.                 printf("SPI1 is Mode fault");
  21.         }

  22.         if(SPI1->SR & 1<<4)                //收到的CRC值和SPI_RXCRCR寄存器中的值不匹配
  23.         {
  24.                 printf("SPI1 is CRC Error");
  25.         }                                       

  26.         printf("SPI1 Error");

  27. }

  28. void SPI2_IRQHandler()
  29. {
  30.         printf("SPI2 Error");

  31. }
Library/src/spi.c
  1. #include "spi.h"

  2. //SPI初始化函数
  3. //SPI1主机模式,SPI2从机模式,8bit数据格式,时钟空闲保持为低,数据采样从第二个时钟边沿开始,波特率 fPCLK/32
  4. //先发送LSB(最低有效位),禁止硬件CRC校验
  5. void Spi_Init(SPI_TypeDef * SPIx)
  6. {
  7.         if(SPIx == SPI1){

  8.                 RCC -> APB2ENR  |= 1<<12;     //SPI1时钟使能
  9.                 RCC -> APB2RSTR |= 1<<12;          //复位SPI1寄存器
  10.                 RCC -> APB2RSTR &= ~(1<<12);  //复位结束SPI1寄存器

  11.                 SPIx -> CR1 |= 1<<2;                 //主设备选择   0:配置为从设备   1:配置为主设备
  12.                 SPIx -> CR1 |= 1<<8;                 //SSI位,要保持主机模式,必须NSS 接到高电平信号       

  13.         }else if(SPIx == SPI2){
  14.                 RCC -> APB1ENR  |= 1<<14;     //SPI2时钟使能
  15.                 RCC -> APB1RSTR |= 1<<14;          //复位SPI2寄存器
  16.                 RCC -> APB1RSTR &= ~(1<<14);  //复位结束SPI2寄存器
  17.                 SPIx -> CR1 |= 0<<2;                 //主设备选择   0:配置为从设备   1:配置为主设备
  18.                 //SPIx -> CR1 |= 0<<8;                 //SSI位,要保持主机模式,必须NSS 接到高电平信号
  19.         }


  20.         SPIx -> CR1 |= 0<<10;                 //设置全双工模式  0:全双工(发送和接收)   1:禁止输出(只接收模式)       
  21.         SPIx -> CR1 |= 0<<11;                 //数据帧格式  0:使用8位数据帧格式进行发送/接收   1:使用16位数据帧格式进行发送/接收
  22.            SPIx -> CR1 |= 1<<7;                 //帧格式                  0:先发送MSB  1:先发送LSB

  23.         //配置NSS为GPIO输出口控制从设备片选
  24.         SPIx -> CR1 |= 1<<9;                 //软件从设备管理 当此位(SSM)被置位时,NSS引脚上的电平由SSI位的值决定。
  25.                

  26.         SPIx -> CR1 |= 0<<1;                 //配置时钟极性 0: 空闲状态时,SCK保持低电平  1: 空闲状态时,SCK保持高电平
  27.         SPIx -> CR1 |= 1<<0;                 //时钟相位     0: 数据采样从第一个时钟边沿开始  1: 数据采样从第二个时钟边沿开始

  28.         SPIx -> CR1 |= 4<<3;                 //波特率控制[5:3]  000: fPCLK/2   001: fPCLK/4   010: fPCLK/8  011: fPCLK/16  100: fPCLK/32
  29.                                                                  //                 101: fPCLK/64        110: fPCLK/128 111: fPCLK/256

  30.         //SPIx -> CR2 |= 1<<7;                 //发送缓冲区空中断使能
  31.         //SPIx -> CR2 |= 1<<6;                 //接收缓冲区非空中断使能
  32.         SPIx -> CR2 |= 1<<5;                 //错误中断使能

  33.         SPIx -> CR1 |= 1<<6;                 //SPI设备使能

  34. }

  35. void Spi_Write(SPI_TypeDef * SPIx,u8 data)
  36. {
  37.         //while((SPIx->SR&1<<1) == 0);        //等待发送缓冲为空置位

  38.         SPIx->DR = data;

  39.         Spi_Delay(3);                                        //必须稍作延时
  40. }


  41. u8 Spi_Read(SPI_TypeDef * SPIx)
  42. {

  43.         //while((SPIx->SR&1<<0) == 1);        //等待接收缓冲非空置位

  44.         return SPIx->DR;

  45. }

  46. void Spi_Delay(u32 us)
  47. {
  48.     u32 time=100*us/7;     
  49.     while(--time);   
  50. }
Library/inc/spi.h
  1. #include <stm32f10x_lib.h>       

  2. void Spi_Init(SPI_TypeDef * SPIx);
  3. void Spi_Write(SPI_TypeDef * SPIx,u8 data);
  4. u8   Spi_Read(SPI_TypeDef * SPIx);
  5. void Spi_Delay(u32 us);


天灵灵地灵灵 发表于 2015-12-24 22:15 | 显示全部楼层
另外就是通过操作库函数
main.c
  1. #include "stm32f10x.h"
  2. #include "stdio.h"
  3. #include "string.h"

  4. #define         PRINTF_ON  1

  5. void RCC_Configuration(void);
  6. void GPIO_Configuration(void);
  7. void USART_Configuration(void);
  8. void SPI_Configuration(void);

  9. #define BufferSize 32

  10. #define delay() for(i=0;i<200;i++)

  11. SPI_InitTypeDef SPI_InitStructure;

  12. u8 SPI1_Buffer_Tx[BufferSize] =                        
  13. {
  14.         0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
  15.         0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,
  16.         0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
  17.         0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20
  18. };

  19. u8 SPI2_Buffer_Tx[BufferSize] =                        
  20. {
  21.         0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,
  22.         0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,
  23.         0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,
  24.         0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70
  25. };

  26. u8 SPI1_Buffer_Rx[BufferSize+1] = {0};
  27. u8 SPI2_Buffer_Rx[BufferSize] = {0};
  28. u8 Tx_Counter = 0;
  29. u8 Rx_Counter = 0;
  30. u8 k=0,i=0;


  31. int main(void)
  32. {
  33.           RCC_Configuration();
  34.         GPIO_Configuration();
  35.         USART_Configuration();
  36.         SPI_Configuration();

  37.         while(Tx_Counter < BufferSize)
  38.         {       
  39.                 SPI_I2S_SendData(SPI2,SPI2_Buffer_Tx[Tx_Counter]);                                //必须从机先发送数据
  40.                 //while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET);         //如果spi2 还有发送缓存则等待发送完成

  41.                 SPI_I2S_SendData(SPI1,SPI1_Buffer_Tx[Tx_Counter]);
  42.                
  43.                 while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE) == RESET);        //没有接收缓存则等待
  44.                 SPI2_Buffer_Rx[Rx_Counter] = SPI_I2S_ReceiveData(SPI2);       

  45.                
  46.                 while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) ==RESET);
  47.                
  48.                 SPI1_Buffer_Rx[Rx_Counter] = SPI_I2S_ReceiveData(SPI1);       

  49.             Tx_Counter++;
  50.                 Rx_Counter++;
  51.         }       

  52.         printf("\r\n The SPI1 has sended data below : \r\n");

  53.         while(k<BufferSize)
  54.         {
  55.                 printf(" %0.2d \r ",SPI1_Buffer_Tx[k]);
  56.                 k++;
  57.         }

  58.         printf("\r\n The SPI2 has received data below : \r\n");

  59.         k=0;

  60.         while(k<BufferSize)
  61.         {
  62.                 printf(" %0.2d \r ",SPI2_Buffer_Rx[k]);
  63.                 k++;
  64.         }

  65.         k=0;

  66.         printf("\r\n The SPI2 has sended data below : \r\n");

  67.         while(k<BufferSize)
  68.         {
  69.                 printf(" %0.2d \r ",SPI2_Buffer_Tx[k]);
  70.                 k++;
  71.         }

  72.         printf("\r\n The SPI1 has received data below : \r\n");

  73.         k=0;

  74.         while(k<BufferSize)
  75.         {
  76.                 printf(" %0.2d \r ",SPI1_Buffer_Rx[k]);
  77.                 k++;
  78.         }

  79.         while(1);       
  80. }

  81. void SPI_Configuration(void)
  82. {

  83.         SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  84.         SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  85.         SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  86.         SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  87.         SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  88.         SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  89.         SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
  90.         SPI_InitStructure.SPI_CRCPolynomial = 7;

  91.         SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  92.         SPI_Init(SPI1,&SPI_InitStructure);
  93.        
  94.         SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
  95.         SPI_Init(SPI2,&SPI_InitStructure);

  96.         SPI_Cmd(SPI1,ENABLE);
  97.         SPI_Cmd(SPI2,ENABLE);

  98. }

  99. void GPIO_Configuration(void)
  100. {
  101.         GPIO_InitTypeDef        GPIO_InitStructure;

  102.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  103.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
  104.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                       
  105.           GPIO_Init(GPIOA , &GPIO_InitStructure);

  106.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;               
  107.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       
  108.           GPIO_Init(GPIOB , &GPIO_InitStructure);


  109.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  110.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                       
  111.           GPIO_Init(GPIOA , &GPIO_InitStructure);
  112.        
  113.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  114.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                       
  115.           GPIO_Init(GPIOA , &GPIO_InitStructure);
  116. }

  117. void RCC_Configuration(void)
  118. {
  119.         /* 定义枚举类型变量 HSEStartUpStatus */
  120.         ErrorStatus HSEStartUpStatus;

  121.           /* 复位系统时钟设置*/
  122.           RCC_DeInit();
  123.           /* 开启HSE*/
  124.           RCC_HSEConfig(RCC_HSE_ON);
  125.           /* 等待HSE起振并稳定*/
  126.           HSEStartUpStatus = RCC_WaitForHSEStartUp();
  127.         /* 判断HSE起是否振成功,是则进入if()内部 */
  128.           if(HSEStartUpStatus == SUCCESS)
  129.           {
  130.             /* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */
  131.             RCC_HCLKConfig(RCC_SYSCLK_Div1);
  132.             /* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */
  133.             RCC_PCLK2Config(RCC_HCLK_Div1);
  134.             /* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */
  135.             RCC_PCLK1Config(RCC_HCLK_Div2);
  136.             /* 设置FLASH延时周期数为2 */
  137.             FLASH_SetLatency(FLASH_Latency_2);
  138.             /* 使能FLASH预取缓存 */
  139.             FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
  140.             /* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */
  141.             RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
  142.             /* 使能PLL */
  143.             RCC_PLLCmd(ENABLE);
  144.             /* 等待PLL输出稳定 */
  145.             while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
  146.             /* 选择SYSCLK时钟源为PLL */
  147.             RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
  148.             /* 等待PLL成为SYSCLK时钟源 */
  149.             while(RCC_GetSYSCLKSource() != 0x08);
  150.           }
  151.           /* 打开APB2总线上的GPIOA时钟*/
  152.           RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_USART1|RCC_APB2Periph_SPI1, ENABLE);

  153.         //RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  154.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
  155.         //RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP|RCC_APB1Periph_WWDG, ENABLE);
  156.                
  157. }


  158. void USART_Configuration(void)
  159. {
  160.         USART_InitTypeDef USART_InitStructure;
  161.         USART_ClockInitTypeDef USART_ClockInitStructure;

  162.         USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
  163.         USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
  164.         USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;                                                                                                                                                      
  165.         USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
  166.         USART_ClockInit(USART1 , &USART_ClockInitStructure);

  167.         USART_InitStructure.USART_BaudRate = 9600;
  168.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  169.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
  170.         USART_InitStructure.USART_Parity = USART_Parity_No;
  171.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  172.         USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
  173.         USART_Init(USART1,&USART_InitStructure);

  174.         USART_Cmd(USART1,ENABLE);
  175. }

  176. #if         PRINTF_ON

  177. int fputc(int ch,FILE *f)
  178. {
  179.         USART_SendData(USART1,(u8) ch);
  180.         while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
  181.         return ch;
  182. }

  183. #endif


kikipu 发表于 2016-2-22 23:48 | 显示全部楼层
好贴,MARK一下,慢慢学习
wangjianxing 发表于 2016-2-23 09:04 | 显示全部楼层
好像要标记一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

40

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部

17

主题

40

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部