STM32:USART串口通信笔记

发布者:平静宁静最新更新时间:2017-09-21 来源: eefocus关键字:stm32  USART  串口通信 手机看文章 扫描二维码
随时随地手机看文章

硬件平台:stm32f10xZET6
开发环境:keil MDK uVision v4.10
开发语言:C、ST_lib_3.5固件库


【串口通信】

typedef struct
{
  u32 USART_BaudRate;
  u16 USART_WordLength;
  u16 USART_StopBits;
  u16 USART_Parity;
  u16 USART_Mode;
  u16 USART_HardwareFlowControl;  
} USART_InitTypeDef;


typedef struct
{
  u16 USART_Clock;
  u16 USART_CPOL;
  u16 USART_CPHA;
  u16 USART_LastBit;
} USART_ClockInitTypeDef;


串口外设主要由三个部分组成,分别是:波特率的控制部分、收发控制部分及数据存储转移部分。


CR1、 CR2、 CR3、SR,即 USART 的三个控制寄存器(Control Register)及一个状态寄存器(Status Register)


当我们需要发送数据时,内核或 DMA 外设把数据从内存(变量)写入到发送数据寄存器 TDR 后,发送控制器将适时地自动把数据从 TDR 加载到发送移位寄存器,然后通过串口线Tx,把数据一位一位地发送出去,在数据从 TDR 转移到移位寄存器时,会产生发送寄存器TDR 已空事件 TXE,当数据从移位寄存器全部发送出去时,会产生数据发送完成事件 TC,这些事件可以在状态寄存器中查询到。
而接收数据则是一个逆过程,数据从串口线 Rx 一位一位地输入到接收移位寄存器,然后自动地转移到接收数据寄存器 RDR,最后用内核指令或 DMA读取到内存(变量)中。


调用了库函数 RCC_APB2PeriphClockCmd()初始化了USART1 和 GPIOA 的时钟,这是因为使用了 GPIOA 的 PA9 和 PA10 的默认复用USART1 的功能,在使用复用功能的时候, 要开启相应的功能时钟 USART1。
/* config USART1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);


在使用外设时,不仅要使能其时钟,还要调用此函数使能外设才可以正常使用。
/* config USART1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
/* 使能串口1接收中断 */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);


USART重要库函数:
USART_SendData()
USART_ReceiveData()
USART_GetFlagStatus()
USART_Init()
USART_ITConfig()
USART_Cmd()


【USART_GetFlagStatus()】
USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) 
USART_FLAG_LBD: LIN Break detection flag 
USART_FLAG_TXE: Transmit data register empty flag 
USART_FLAG_TC: Transmission Complete flag 
USART_FLAG_RXNE: Receive data register not empty flag 
USART_FLAG_IDLE: Idle Line detection flag 
USART_FLAG_ORE: OverRun Error flag 
USART_FLAG_NE: Noise Error flag 
USART_FLAG_FE: Framing Error flag 
USART_FLAG_PE: Parity Error flag 


【USART_ITConfig()】
USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5) 
USART_IT_LBD: LIN Break detection interrupt 
USART_IT_TXE: Transmit Data Register empty interrupt 
USART_IT_TC: Transmission complete interrupt 
USART_IT_RXNE: Receive Data register not empty interrupt 
USART_IT_IDLE: Idle line detection interrupt 
USART_IT_PE: Parity Error interrupt 
USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)


串口的发送中断有两个,分别是:
>>发送数据寄存器空中断(TXE)
>>发送完成中断(TC)
一般来说我们会使用发送数据寄存器空中断,用这个中断发送的效率会高一些。


keil的虚拟串口Debug调试:
需要设置为 Use Simulator模式
开启 View-command window输入命令

MODE COM1 115200,0,8,1
ASSIGN COM1 S1OUT
技巧:【Debug】选项卡下左侧 Initialization File 中点击【...】 新增一个默认调试命令的.ini文件,如debug.ini

虚拟串口软件 VSPD 开启两个COM,使用secureCRT连接另外一个COM口,查看接收情况


第一个AT指令是“ATE0Q0V1”,很是迷惑了一阵,后来才明白这是三个指令的合并:”ATE0+ATQ0+ATV1“。
ATE0:不回显字符。
ATE1:回显字符。
ATQ0:  返回结果码。
ATQ1:不返回结果吗。
ATV0:返回数字码。
ATV1: 返回文字码。




记录下接线颜色对应管脚


>>usart1连USB-TTL
    重定向printf到usart1
    往usart1发AT
    终端测试
>>usart1连GPRS,usart2连USB-TTL
    往usart1发AT
    逐个字符收数据到公共缓冲区
    使用usart2重定向的printf输出缓冲区内容
    终端测试






// 中断处理函数需:时钟配置、中断配置、USART中的接收中断使能、中断处理函数
void USART1_IRQHandler(void)
{
uint8_t ch;

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

   //ch = USART1->DR;
ch = USART_ReceiveData(USART1);
  printf( "%c", ch );    //将接受到的数据直接返回打印

 
}
-----------------------------------------------------------
char buf[70] = {0}; // 全局缓冲区,extern调用
void USART1_IRQHandler(void)
{
uint8_t ch;
    int index = 0;

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

   //ch = USART1->DR;
buf[index] = USART_ReceiveData(USART1);
  printf( "%c", buf[index]);    //将接受到的数据通过usart1的printf打印显示
        index++;
    }  

}



  1. // usart.c  

  2.   

  3. #include "usart.h"  

  4.   

  5. extern sdstring atcmd_recv_buff;  

  6.   

  7.  /** 

  8.   * @ USART1 GPIO 配置,工作模式配置。115200 8-N-1 

  9.   */  

  10. void USART1_Config(void)  

  11. {  

  12.     GPIO_InitTypeDef GPIO_InitStructure;  

  13.     USART_InitTypeDef USART_InitStructure;  

  14.       

  15.     /* 配置 USART1 时钟 */  

  16.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);  

  17.       

  18.     /* USART1 GPIO 配置 */  

  19.     /* 配置 USART1 Tx (PA9) 为复用推挽输出模式,速度50MHZ */  

  20.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  

  21.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  

  22.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

  23.     GPIO_Init(GPIOA, &GPIO_InitStructure);  

  24.   

  25.     /* 配置 USART1 Rx (PA10) 为浮空输入模式 */  

  26.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  

  27.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  

  28.     GPIO_Init(GPIOA, &GPIO_InitStructure);  

  29.           

  30.     /* USART1 工作参数配置: 

  31.         - BaudRate = 115200 baud   

  32.         - Word Length = 8 Bits 

  33.         - One Stop Bit 

  34.         - No parity 

  35.         - Hardware flow control disabled (RTS and CTS signals) 

  36.         - Receive and transmit enabled 

  37.     */  

  38.     USART_InitStructure.USART_BaudRate = 115200;  

  39.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  

  40.     USART_InitStructure.USART_StopBits = USART_StopBits_1;  

  41.     USART_InitStructure.USART_Parity = USART_Parity_No ;  

  42.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  

  43.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  

  44.     USART_Init(USART1, &USART_InitStructure); // 写入初始化信息  

  45.   

  46.     USART_Cmd(USART1, ENABLE);             /* 使能 USART1  */  

  47. }  

  48.   

  49.  /** 

  50.   * @ USART1 NVIC 中断配置 

  51.   */  

  52. void NVIC_Config(void)  

  53. {  

  54.     NVIC_InitTypeDef NVIC_InitStructure;  

  55.        

  56.     /* 配置 NVIC 优先组0 (4位的16级优先级可选 - 0~15) */    

  57.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);  

  58.       

  59.     /* 使能USART1中断 */  

  60.     NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;      

  61.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 0  

  62.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 1~15  

  63.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

  64.     NVIC_Init(&NVIC_InitStructure);  

  65. }  

  66.   

  67. // usart1中断处理函数在 stm32f10x_it.c line:156  

  68.   

  69.  /** 

  70.   * @ USART2 GPIO 配置,工作模式配置。115200 8-N-1 

  71.   */  

  72. void USART2_Config(void)  

  73. {  

  74.     GPIO_InitTypeDef  GPIO_InitStructure;  

  75.     USART_InitTypeDef USART_InitStructure;  

  76.       

  77.     sds_clean(&atcmd_recv_buff); // 接收前初始化清理一次公共缓冲区  

  78.       

  79.     /* 使能 USART2 时钟 */  

  80.     RCC_APB1PeriphClockCmd (RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);   

  81.       

  82.     /* 配置 USART2 Tx (PA2) 为复用推挽输出模式,速度50MHz */  

  83.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;  

  84.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;  

  85.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

  86.     GPIO_Init(GPIOA, &GPIO_InitStructure);  

  87.   

  88.     /* 配置 USART2 Rx (PA3) 为输入浮空模式 */  

  89.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3;  

  90.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;  

  91.     GPIO_Init(GPIOA, &GPIO_InitStructure);  

  92.       

  93.     /* USART2 工作参数配置: 

  94.         - BaudRate = 115200 baud   

  95.         - Word Length = 8 Bits 

  96.         - One Stop Bit 

  97.         - No parity 

  98.         - Hardware flow control disabled (RTS and CTS signals) 

  99.         - Receive and transmit enabled 

  100.     */  

  101.     USART_InitStructure.USART_BaudRate            = 115200;  

  102.     USART_InitStructure.USART_WordLength          = USART_WordLength_8b;  

  103.     USART_InitStructure.USART_StopBits            = USART_StopBits_1;  

  104.     USART_InitStructure.USART_Parity              = USART_Parity_No;  

  105.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  

  106.     USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;  

  107.     USART_Init(USART2, &USART_InitStructure); // 写入初始化信息  

  108.       

  109.     /* 使能串口2接收中断 */  

  110.     USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  

  111.   

  112.     USART_Cmd(USART2, ENABLE);            /* 使能 USART2  */    

  113. }  

  114.   

  115.   

  116. /* USART1 - 发送字符、接收字符 (轮询也用于printf重定向)    */  

  117. int SendChar (int ch)  {                                            /* 发送字符 8bit/byte     */   

  118.   USART_SendData(USART1, (unsigned char) ch);                       /* 将1字节数据发往串口寄存器 */       

  119.   // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);   /* 轮询等待传输结束 */  

  120.   while (!(USART1->SR & USART_FLAG_TXE));  

  121.   return ch;  

  122. }  

  123.   

  124. int GetData (void)  {                                               /* 读取字符 8bit/byte    */  

  125.   while (!(USART1->SR & USART_FLAG_RXNE));  

  126.   return (USART_ReceiveData(USART1));  

  127. }  

  128.   

  129. /* USART2 - 发送字符、接收字符 (轮询也用于printf重定向)    */  

  130. int SendCharSerail2 (int ch)  {                                     /* 发送字符 8bit/byte     */  

  131.   USART_SendData(USART2, (unsigned char) ch);  

  132.   while (!(USART2->SR & USART_FLAG_TXE));  

  133.   return (ch);  

  134. }  

  135.   

  136. int GetDataSerial2 (void)  {                                        /* 读取字符 8bit/byte    */  

  137.   

  138.   while (!(USART2->SR & USART_FLAG_RXNE));  

  139.   return (USART_ReceiveData(USART2));  

  140. }  

  141.   

  142.   

  143.   

  144. /*********************************************END OF FILE**********************/  


  1. // retarget.c  

  2.             

  3. #include   

  4. #include   

  5. #include "usart.h"  

  6.   

  7. /* 

  8.  * 函数名: fputc 

  9.  * 描述 : 重定向 c 库函数 printf 到 USART1 

  10.  */  

  11. int fputc(int ch, FILE *f)  

  12. {  

  13. #if 1  // 1-USART1 : 0-USART2     

  14.     USART_SendData(USART1, (unsigned char) ch); // 将1字节数据发往串口寄存器,printf测试usart2回显     

  15.     while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); // 轮询是否发送完成,标志位TC        

  16. #else  

  17.     USART_SendData(USART2, (unsigned char) ch); // 将1字节数据发往串口寄存器      

  18.     while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); // 轮询是否发送完成,标志位TC  

  19. #endif  

  20.     return (ch);  

  21. }  

  22.   

  23. // 从USART中的数据  

  24. int fgetc(FILE *f)   

  25. {  

  26. #if 1  

  27.     return (SendChar (GetData ()));  

  28. #else  

  29.     return (SendCharSerail2 (GetData ()));  

  30. #endif  

  31. }  


  1. // at_cmd.c  

  2.   

  3. #include "at_cmd.h"  

  4. sdstring atcmd_recv_buff; //atcmd_recv_buff.buff 全局缓冲区,存放返回数据  

  5.   

  6. // 逐个发送AT命令集  

  7. void send_all_at_cmd (void)  

  8. {  

  9.     char *p_res = NULL;  

  10.     char *p_str = "hello";  

  11.   

  12.     send_at_cmd (AT_AT);  

  13.     p_res = receive_data ();  

  14.     print_log_info ("recv data");  

  15.     // if "OK"/0  

  16.     if (! strstr (p_res, "OK")) {  

  17.         return ;  

  18.     }  

  19.   

  20.     send_at_cmd (AT_CGATT);  

  21.     p_res = receive_data ();  

  22.     print_log_info ("recv data");  

  23.     // if "OK"/0  

  24.   

  25.     send_at_cmd (AT_CGATT_1);  

  26.     p_res = receive_data ();  

  27.     print_log_info ("recv data");  

  28.     // if "OK"/0  

  29.   

  30.     send_at_cmd (AT_CON_TCP);  

  31.     p_res = receive_data ();  

  32.     print_log_info ("recv data");  

  33.     // if "CONNECT OK"  

  34.             

  35.     send_at_cmd (AT_CIPSEND);  

  36.     p_res = receive_data ();  

  37.     print_log_info ("recv data");  

  38.     // if ">"  

  39.   

  40.     send_at_cmd (p_str);  

  41.     p_res = receive_data ();  

  42.     print_log_info ("recv data");  

  43.     // if "HTTP/1.1 400 Bad Request"  

  44.   

  45. #if 0  

  46.     send_at_cmd (AT_CIPCLOSE); // 关闭TCP连接命令  

  47.     p_res = receive_data ();  

  48.     print_log_info ("recv cmd");  

  49.     // if "OK"/0  

  50. #endif  

  51. }  

  52.   

  53. // 发送单个AT命令,打印提示日志  

  54. void send_at_cmd (char *p_cmd)  

  55. {  

  56.     //int i = 0;  

  57. #if 1  

  58.     send_USART2 (p_cmd, strlen (p_cmd));  

  59.     send_USART2 (AT_CONFIRM, strlen (AT_CONFIRM)); // \r\n  

  60.     strcpy (atcmd_recv_buff.buff, p_cmd);  

  61.     print_log_info ("send cmd");  

  62. #else  

  63.     // 发送什么指令-回显到屏幕(USART1重定向了printf)单向传输测试  

  64.     printf ("\r\n%s", p_cmd);  

  65. #endif  

  66. }  

  67.   

  68. // 接收发送命令后GPRS通过串口端自动回复的数据  

  69. char* receive_data (void)  

  70. {  

  71.     int i;  

  72.     memset (atcmd_recv_buff.buff, 0, sizeof (atcmd_recv_buff.buff));   

  73. #if 1  

  74.     // 轮询读取USART2接收寄存器的信息到atcmd_recv_buff.buff[]  

  75.     do {              

  76.         while(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET);  

  77.         atcmd_recv_buff.buff[i] = USART2->DR;  

  78.         // 如果在USART2的接收寄存器中接收到 \n 字符,作为结束标志  

  79.         if(atcmd_recv_buff.buff[i] == '\n') {  

  80.             break;  

  81.         }  

  82.         i++;  

  83.     } while(1);  

  84.     return (atcmd_recv_buff.buff);  

  85. #else // used to test... 测试返回数据  

  86.     memset (atcmd_recv_buff.buff, 0, sizeof (atcmd_recv_buff.buff));  

  87.     strcpy (atcmd_recv_buff.buff, "OK\r\n");  

  88.     return (atcmd_recv_buff.buff);  

  89. #endif        

  90. }  

  91.   

  92. // 往连接GPRS串口的USART2串口中发送字符串数据  

  93. void send_USART2 (char *pdata, int len)  

  94. {  

  95.     int index = 0;  

  96.     for(index = 0; index < len; index++)  

  97.     {  

  98.         SendCharSerail2(pdata[index]);  

  99.     }  

  100. }  

  101.   

  102. /* 

  103. // 测试IP:123.58.34.245  测试端口:80 

  104. void send_connect_cmd (char *ip,int port)  

  105.     char buf[40]={0}; 

  106.     send_at_cmd (AT_CIPSTART); 

  107.     snprintf(buf, sizeof(buf), "\"%s\",%d", ip, port); 

  108.     send_at_cmd (buf);   

  109. */  

  110.   

  111. // 打印输出全局缓冲区内容,即日志,通过USART1重定向了printf后显示到串口终端  

  112. void print_log_info (char *p_str)  

  113. {  

  114.     printf ("\r\n%s:%s", p_str, atcmd_recv_buff.buff);  

  115. }  

  116.   

  117. // 字符串清理  

  118. void sds_clean(sdstring *psds)  

  119. {  

  120.     memset(psds->buff, 0, sizeof(psds->buff));  

  121.     psds->pos=0;  

  122.       

  123. }  

  124. // 字符串长度  

  125. int  sds_length(sdstring *psds)  

  126. {  

  127.     return psds->pos;  

  128. }  

  129. // 字符串追加  

  130. int sds_append_char(sdstring *psds, char ch)  

  131. {  

  132.     if(psds->pos >= sizeof(psds->buff)-1)  

  133.     {  

  134.         return -1;  

  135.     }     

  136.     psds->buff[psds->pos]=ch;  

  137.     psds->pos++;  

  138.     return 0;  

  139. }  


  1. // at_cmd.h  

  2. #pragma once  

  3.   

  4. #include   

  5. #include   

  6. #include "usart.h"  

  7. #include "setup.h"  

  8.   

  9. /*--------------发送-----------------*/  

  10. // at命令头  

  11. #define AT_CMD_PREFIX       "AT+"  

  12.   

  13. #define CHAR_PLUS           '+'  

  14. #define CHAR_CR             '\r'  

  15. #define CHAR_POWER          '^'  

  16.   

  17. #define AT_CONFIRM          "\r\n"  

  18.   

  19. #define AT_FORMAT           "ATE0Q0V1"              // ATE1/0 回显/不回显字符; ATQ1/0 返回/不返回结果码; ATV1/0 返回/不返回结果码  

  20.                                                     // ATV1/0 决定了收到GPRS模块回复的数据是 <字符串> OK 或 <数字> 0  

  21.   

  22. #define AT_AT               "AT"                    // AT命令测试,返回OK  

  23. #define AT_ATI              "ATI"                   // 查询固件版本信息  

  24. #define AT_CCID             "AT+CCID"               // 查询SIM ,CCID用于判断是否插卡  

  25. #define AT_CREG             "AT+CREG?"              // 查询网络注册情况  

  26. #define AT_CGATT            "AT+CGATT=1"            // 1.附着网络,返回OK  

  27. #define AT_CGATT_1          "AT+CGACT=1,1"          // 2.激活PDP,返回OK,即可正常上网  

  28. #define AT_CIPSTART         "AT+CIPSTART=\"TCP\","  // 连接服务端  

  29.   

  30. #define AT_CON_TCP          "AT+CIPSTART=\"TCP\",\"123.58.34.245\",80" // 连接服务端,IP和PORT目前为测试取值  

  31. #define AT_CON_IP           "123.58.34.245"  

  32. #define AT_CON_PORT         80  

  33.   

  34. #define AT_CIPSEND          "AT+CIPSEND=20"         // 返回>,就可以输入要发送的内容20表示有20个字节  

  35. #define AT_TMP_STRING       "1234567890123456789"   // 19个字符有效字符  

  36.   

  37. #define AT_CIPCLOSE         "AT+CIPCLOSE=1"         // 关闭连接  

  38. #define AT_CIPSHUT          "AT+CIPSHUT"            // 关闭 GPRS/CSD PDP 场景  

  39.   

  40.      

  41. #define AT_CIPTMODE_START   "AT+CIPTMODE=1"     // 启动透传模式  

  42. #define AT_CIPTMODE_QUIT    "AT+CIPTMODE=0"     // 停止透传模式  

  43.   

  44. #define PARSE_CMD_OK        0  

  45. #define PARSE_CMD_ERR       -1  

  46. #define PARSE_CMD_NEEDMORE  1  

  47.   

  48. typedef struct _sdstring {  

  49.     int pos;  

  50.     char buff[128];  

  51. } sdstring;  

  52.   

  53. // 逐个发送AT命令集  

  54. void  send_all_at_cmd (void);  

  55. // 发送单个AT命令,打印提示日志  

  56. void  send_at_cmd (char * p_cmd);  

  57. // 接收发送命令后GPRS通过串口端自动回复的数据  

  58. char* receive_data (void);  

  59. // 往连接GPRS串口的USART2串口中按字节(8bit)逐个发送数据  

  60. void  send_USART2 (char *pdata, int len);  

  61. // 打印输出全局缓冲区,即每次数据收发的日志信息  

  62. void  print_log_info (char *p_str);  

  63.   

  64. // void  send_connect_cmd (char *ip,int port);  

  65.   

  66. // 字符串处理  

  67. void  sds_clean(sdstring *psds);  

  68. int   sds_append_char(sdstring *psds, char ch);  

  69. int   sds_length(sdstring *psds);  

  70.   

  71. // 自定义的格式化输出  

  72. // void USART1_printf(USART_TypeDef* USARTx, uint8_t *Data,...)  


  1. // setup.c  

  2.     

  3. #include "Setup.h"  

  4.   

  5. static __IO u32 TimingDelay;  

  6.    

  7. /** 

  8.   * @brief      启动系统滴答定时器 SysTick 

  9.   */  

  10. void SysTick_Init(void)  

  11. {  

  12.     /* SystemFrequency / 1000    1ms中断一次 

  13.      * SystemFrequency / 100000  10us中断一次 

  14.      * SystemFrequency / 1000000 1us中断一次 

  15.      */  

  16. //  if (SysTick_Config(SystemFrequency / 100000))   // ST3.0 库版本  

  17.     if (SysTick_Config(SystemCoreClock / 100000))   // ST3.5 库版本  

  18.     {   

  19.         /* Capture error */   

  20.         while (1);  

  21.     }  

  22.     // 关闭滴答定时器    

  23.     SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;  

  24. }  

  25.   

  26. /** 

  27.   * @brief      us延时程序,10us为一个单位 

  28.   * @arg nTime  Delay_us( 1 ) 则实现的延时为 1 * 10us = 10us 

  29.   */  

  30. void Delay_us(__IO u32 nTime)  

  31. {   

  32.     TimingDelay = nTime;      

  33.   

  34.     // 使能滴答定时器    

  35.     SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;  

  36.   

  37.     while(TimingDelay != 0);  

  38. }  

  39.   

  40. /** 

  41.   * @brief      获取节拍程序 

  42.   * @attention  在 SysTick 中断函数 SysTick_Handler()调用 

  43.   */  

  44. void TimingDelay_Decrement(void)  

  45. {  

  46.     if (TimingDelay != 0x00)  

  47.     {   

  48.         TimingDelay--;  

  49.     }  

  50. }  

  51. /*********************************************END OF FILE**********************/  




  1. // led.h  

  2. #ifndef __LED_H  

  3. #define __LED_H  

  4.   

  5. #include "stm32f10x.h"  

  6.   

  7. #define ON  0  

  8. #define OFF 1  

  9.   

  10. /* 带参宏,可以像内联函数一样使用 */  

  11. #define LED1(a) if (a)                              \  

  12.                     GPIO_SetBits(GPIOB,GPIO_Pin_5); \  

  13.                     else                            \  

  14.                     GPIO_ResetBits(GPIOB,GPIO_Pin_5)  

  15.   

  16. #define LED2(a) if (a)                              \  

  17.                     GPIO_SetBits(GPIOE,GPIO_Pin_5); \  

  18.                     else                            \  

  19.                     GPIO_ResetBits(GPIOE,GPIO_Pin_5)  

  20.   

  21. void LED_Config(void);  

  22.   

  23. #endif // __LED_H   

  24.   

  25. // led.c  

  26.     

  27. #include "led.h"     

  28.   

  29.  /* 

  30.   * @ LED 初始化I/O控制 

  31.   */  

  32. void LED_Config(void)  

  33. {         

  34.         /*定义一个GPIO_InitTypeDef类型的结构体*/  

  35.         GPIO_InitTypeDef GPIO_InitStructure;  

  36.   

  37.         /*开启GPIOB的外设时钟*/  

  38.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE);   

  39.   

  40.         /*设置引脚模式为通用推挽输出*/  

  41.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     

  42.         /*设置引脚速率为50MHz */     

  43.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

  44.   

  45.         /*选择要控制的GPIOB引脚*/                                                                

  46.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;              

  47.         /*调用库函数,初始化GPIOB5*/  

  48.         GPIO_Init(GPIOB, &GPIO_InitStructure);  

  49.   

  50.         /*选择要控制的GPIOE引脚*/                                                                

  51.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;              

  52.         /*调用库函数,初始化GPIOE5*/  

  53.         GPIO_Init(GPIOE, &GPIO_InitStructure);            

  54.           

  55.         /* 关闭led灯 */  

  56.         GPIO_SetBits(GPIOB, GPIO_Pin_5);  

  57.         GPIO_SetBits(GPIOE, GPIO_Pin_5);  

  58. }  

  59. /*********************************************END OF FILE**********************/  



关键字:stm32  USART  串口通信 引用地址:STM32:USART串口通信笔记

上一篇:STM32之USART 232串口通信<一>
下一篇:STM32:I2C接口读写EEPROM(AT24C02)试验例程

推荐阅读最新更新时间:2024-03-16 15:37

STM32】2-STM32中断系统(NVIC)
一、中断介绍 1.1 中断概念 CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,转去执行一段特殊的服务程序(中断服务子程序或中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序继续执行,这一过程称为中断。引发中断的称为中断源。比如:看电视时突然门铃响,那么门铃响就相当于中断源。有些中断还能够被其他高优先级的中断所中断,那么这种情况又叫做中断的嵌套。 STM32F10x芯片有84个中断通道,包括 16 个内核中断和 68 个可屏蔽中断,这些中断通道已按照不同优先级顺序固定分配给相应的外部设备。(参考《STM32F10x中文参考手册》-9 中断和事件章节) 1.2 NVI
[单片机]
【<font color='red'>STM32</font>】2-STM32中断系统(NVIC)
再造STM32---第一部分:如何正规的安装KEIL5?
获取本文所有安装包和注册机方式: 1、CSDN下载: https://download.csdn.net/download/qq_38351824/10943718 2、可以关注点赞并在下方评论,我给你邮箱发过去。 3、关注微信公众号下载: ① 关注微信公众号:Tech云 ② 一、温馨提示: 1、 安装路径不能带中文,必须是英文路径 2、 安装目录不能跟 51 的 KEIL 或者 KEIL4 冲突,三者目录必须分开 3、 KEIL5 的安装比起 KEIL4 多了一个步骤,必须添加 MCU 库,不然没法使用。 4、 如果使用的时候出现莫名其妙的错误,先百度查找解决方法,莫乱阵脚。 二、获取 KEIL5
[单片机]
再造STM32---第一部分:如何正规的安装KEIL5?
STM32入门学习笔记之外置FLASH读写实验
15.1 FLASH Flash,全名叫做Flash EEPROM Memory,即平时所说的“闪存”,它结合了ROM和RAM的长处,不仅可以反复擦除,还可以快速读取数据,STM32运行的程序其实就是存放在Flash当中,但是由于STM32的Flash一般1M左右,只能存储程序大小的数据,所以往往需要外扩Flash来存储数据,比如LCD界面当中的汉字字库,以及文件系统中读取的文件内容。 但是一般Flash的擦除次数有限制,STM32F1系列最新的文档指出,片内的FLASH擦写次数大约在1W次左右,所以一般Flash用于擦除次数不多,但是数据量很大的场合。 这个Flash读写实验我们用到的芯片是W25Q128,这是一款采用S
[单片机]
<font color='red'>STM32</font>入门学习笔记之外置FLASH读写实验
STM32 CubeMX按键中断
一、GPIO 8种工作模式 输入模式: 1. GPIO_Mode_AIN 模拟输入 2. GPIO_Mode_IN_FLOATING 浮空输入 3. GPIO_Mode_IPD 下拉输入 4. GPIO_Mode_IPU 上拉输入 输出模式: 5. GPIO_Mode_Out_OD 开漏输出 6. GPIO_Mode_Out_PP 推挽输出 7. GPIO_Mode_AF_OD 复用开漏输出 8. GPIO_Mode_AF_PP 复用推挽输出 施密特触发器:当输入电压高于正向阈值电压,输出为高;当输入电压低于负向阈值电压,输出为低;当输入在正负向阈值电压之间,输出不改变,只有当输入电压发生足够的变化
[单片机]
<font color='red'>STM32</font> CubeMX按键中断
Crypto算法库使用技巧之基于STM32 AES GCM应用提示
引言 X-CUBE-CRYPTOLIB 是基于 STM32 的 Crypto 算法库,支持对称密钥、非对称密钥、哈希等多种算法。正确地使用 Cyrptolib 算法库,可以在应用程序中实现数据加密、设备身份认证、加密通信等多种应用层所需的安全功能。相反,若不能正确地使用算法库往往会带来加解密数据错误等系列问题。 关于 STM32 Crypto 算法库应用中的常见的问题之一就是应用程序没有使能 MCU 的CRC 模块,尽管输出的数据和期望值不同,但加解密函数的调用并未返回异常。本文在此描述另外一种没有正确使用算法库的情况。 问题描述 客户应用项目中需要在固件更新过程中对固件进行加密并验证,根据推荐采用了 AES- GCM 算
[单片机]
RyanMqtt移植指南
测试环境:stm32F401RCT6、RT-Thread版本: v4.1.0、RT-Thread Studio版本: 2.2.6、网络硬件使用ec800m移植at_socket使用sal框架。 1、移植介绍 RyanMqtt 库希望应用程序为以下接口提供实现: system 接口 RyanMqtt 需要 RTOS 支持,必须实现如下接口才可以保证 mqtt 客户端的正常运行 network 接口 RyanMqtt 依赖于底层传输接口 API,必须实现该接口 API 才能在网络上发送和接收数据包 MQTT 协议要求基础传输层能够提供有序的、可靠的、双向传输(从客户端到服务端 和从服务端到客户端)的字节流 time 接口
[单片机]
RyanMqtt移植指南
STM32 IIC难点易错点
先来点题外话~网上说STM32F103的IIC有瑕疵!就当是有些短板吧,个人觉得,用起来肯定没问题,只是不好用。因为ST公司考虑到专利问题,所以没按飞利浦的标准来。导致STM32的IIC使用起来非常繁杂。下面就讲讲用STM32 IO口模拟IIC的注意问题: IIC总线时序: 进入正题→_→博主就因为没理解好应答,吃了亏。讲一讲IIC的几个重要状态: 1、空闲状态:当IIC总线空闲时,SDA和SCL两条线均为高电平,由于连接到总线上的器件必须是漏级和集电极开路(至于威为什么请读者自己搜索),只要有一个器件任意时刻输出低电平,都将使总线上的信号变低,即各器件的SDA和SCL是线与的关系。由于各器件输出端是漏级开路,故必须通
[单片机]
<font color='red'>STM32</font> IIC难点易错点
STM32 usb_mem.c和usb_sil.c文件的分析
这两个c文件都还算是很简单的,先讲讲usb_mem.c这个文件。从文件名就能知道跟内存有关,这个文件主要定义了两个函数,一个读双缓冲区PMA的数据PMAToUserBufferCopy(),另一个是写数据到双缓冲区PMA,UserToPMABufferCopy。如果,当你的usb设备接收到了数据,当然数据存放在PMA中了,我们要读出数据就要用到PMAToUserBufferCopy()函数了,如果我们想要发送数据给usb主机,就要将你要发送的数据拷贝到PMA缓冲区中了,这样才能发送出去,原理跟串口类似。 /*************************************************************
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多精选电路图
换一换 更多 相关热搜器件
更多每日新闻
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved