找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6889|回复: 1
打印 上一主题 下一主题
收起左侧

STM32F407的串口编程经验

[复制链接]
跳转到指定楼层
楼主
ID:417196 发表于 2018-10-29 13:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32F407的串口编程经验
串口是嵌入式开发中最常前的外设设备,既可以用作不同单片机之间的通信,也可以用作在STM32 MCU和PC机之间的通信,STM32F407的串口功能非常强大,可以接红外,可以接流控,也可以接SIM卡接口,但我这里只介绍我们最常用的UART通信的一点调试经验,以STM32F407为例,对其它STM32芯片也适用,希望对大家有所帮助,如有错误不当之处欢迎大家联系指正。
一、串口的三种工作方式操作串口一般有两种方式:查询和中断;STM32还支持第三种DMA方式。(1)查询:串口程序不断地循环查询标志,看看当前有没有数据要它传送或接收。如果有的话进行相应的写操作和读操作进行传送或接收数据。(2)中断:平时串口只要打开中断即可。如果发现有一个中断来,则意味着有数据需要接收(接收中断)或数据已经发送完成(发送中断)。(3)DMA方式,设置好DMA工作方式,由DMA来自动接收或发送数据。一般来说,查询方式的效率是比较低的,并且由于STM32的UART硬件上没有FIFO,如果程序功能比较多,查询不及时的话很容易出现数据丢失的现象, 故实际项目中这种方式用的并不多。中断方式的话我们可以分别设置接收中断和发送中断,当串口有数据需要接收时才进入中断程序进行读读操,这种方式占用CPU资源比较少,实际项目中比较常用,但需要注意中断程序不要太复杂使执行时间太长,如果执行时间超过一个字符的时间的话也会出现数据丢失的现象,这个波特率比较高的串口编程中比较容易出现,可以考虑用循环BUF方法,在中断程序中只负责实时地接收实数数和发送时的填数(写发送寄存器),其它操作放在中断外处理。STM32还提供了第三种DMA方式用来支持高速地串口传输。这种方式只要设置好接收和发送缓冲位置,可以由DMA来自动接收和发送数据,这可以最小化占用CPU时间。
二、串口的使用步骤(1)中断方式基本步骤是初试化时钟,脚位、波特率设置、安装中断服务程序、开中断等,参考代码如下:
1.    voiduart_init(void)
2.    {
3.      USART_InitTypeDef USART_InitStructure;
4.      NVIC_InitTypeDefNVIC_InitStructure;
5.      GPIO_InitTypeDef  GPIO_InitStructure;
6.      
7.      /*Enable GPIO clock  */
8.      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
9.      
10.     /* Enable USART clock */
11.    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
12.   
13.     /* Connect USART pins to AF7 */
14.     GPIO_PinAFConfig(GPIOC, GPIO_PinSource10,GPIO_AF_USART3);
15.    GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,  GPIO_AF_USART3);
16.     
17.    /* Configure USART Tx and Rx as  alternatefunction push-pull */
18.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
19.    GPIO_InitStructure.GPIO_Speed=  GPIO_Speed_100MHz;
20.     GPIO_InitStructure.GPIO_OType =GPIO_OType_PP;
21.    GPIO_InitStructure.GPIO_PuPd=  GPIO_PuPd_UP;
22.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
23.    GPIO_Init(GPIOC,  &GPIO_InitStructure);
24.     
25.    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11;
26.    GPIO_Init(GPIOC,  &GPIO_InitStructure);
27.    /*  USARTxconfiguration  ----------------------------------------------------*/
28.    /* USARTx configured as follow:
29.          - BaudRate =3750000 baud
30.    - Maximum BaudRate that can be achievedwhen  using the Oversampling by 8
31.       is: (USART APB Clock / 8)
32.  Example:
33.     - (USART3 APB1  Clock / 8) = (30MHz / 8) = 3750000 baud
34.     - (USART1 APB2 Clock / 8) = (60 MHz / 8) =7500000  baud
35.    - Maximum BaudRate that can  beachieved when using the Oversampling by 16
36.      is: (USART APB Clock / 16)
37.  Example: (USART3 APB1 Clock / 16) = (30 MHz /16)  = 1875000 baud
38.  Example: (USART1  APB2 Clock / 16) = (60 MHz /16) = 3750000 baud
39.          - Word Length = 8Bits
40.          - one Stop Bit
41.          - No parity
42.          - Hardware flowcontrol disabled (RTS and  CTS signals)
43.          - Receiveand  transmit enabled
44.     */
45.     USART_InitStructure.USART_BaudRate = 115200;
46.    USART_InitStructure.USART_WordLength=  USART_WordLength_8b;
47.     USART_InitStructure.USART_StopBits =USART_StopBits_1;
48.    USART_InitStructure.USART_Parity=  USART_Parity_No;
49.    USART_InitStructure.USART_HardwareFlowControl=  USART_HardwareFlowControl_None;
50.     USART_InitStructure.USART_Mode =USART_Mode_Rx | USART_Mode_Tx;
51.    USART_Init(USART3,  &USART_InitStructure);
52.     
53.    /* NVIC configuration  */
54.    /* Configure the Priority  Group to2 bits */
55.    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
56.   
57.     /* Enable the USARTx Interrupt */
58.    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
59.    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
60.    NVIC_InitStructure.NVIC_IRQChannelSubPriority=  0;
61.     NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
62.     NVIC_Init(&NVIC_InitStructure);
63.   
64.    /* Enable USART  */
65.    USART_Cmd(USART3,  ENABLE);
66.    USART_ITConfig(USART3,  USART_IT_RXNE,ENABLE);
67.  }
68.   
复制代码

中断服务程序如下:
1.    voidUSART3_IRQHandler(void)
2.    {
3.    unsigned charch;  
4.    if(USART_GetITStatus(USART3,  USART_IT_RXNE)!= RESET)
5.       {
6.       /* Read one byte from the  receive data register */
7.       ch =  (USART_ReceiveData(USART3));
8.     
9.        printf("in[%c].\r\n",ch);
10.    }   
11.  }
复制代码


直接把接收到的字符打印出来。
(2)DMA方式基本步骤同中断方式,额外需要DMA的初始化配置,参考代码如下:
1.    void  uart_init(void)
2.    {
3.      USART_InitTypeDef  USART_InitStructure;
4.      NVIC_InitTypeDef NVIC_InitStructure;
5.      GPIO_InitTypeDefGPIO_InitStructure;
6.      DMA_InitTypeDefDMA_InitStruct;
7.      
8.       /*Enable GPIO clock */
9.      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
10.   
11.     /* Enable USART clock */
12.    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
13.   
14.     /* Connect USART pins to AF7 */
15.     GPIO_PinAFConfig(GPIOC, GPIO_PinSource10,GPIO_AF_USART3);
16.    GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,  GPIO_AF_USART3);
17.     
18.    /* Configure USART Tx and Rx as  alternatefunction push-pull */
19.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
20.    GPIO_InitStructure.GPIO_Speed=  GPIO_Speed_100MHz;
21.     GPIO_InitStructure.GPIO_OType =GPIO_OType_PP;
22.    GPIO_InitStructure.GPIO_PuPd=  GPIO_PuPd_UP;
23.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
24.    GPIO_Init(GPIOC,  &GPIO_InitStructure);
25.     
26.    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11;
27.    GPIO_Init(GPIOC,  &GPIO_InitStructure);
28.    /*  USARTxconfiguration  ----------------------------------------------------*/
29.    /* USARTx configured as follow:
30.          - BaudRate =3750000 baud
31.    - Maximum BaudRate that can be achievedwhen  using the Oversampling by 8
32.       is: (USART APB Clock / 8)
33.  Example:
34.     - (USART3 APB1  Clock / 8) = (30MHz / 8) = 3750000 baud
35.     - (USART1 APB2 Clock / 8) = (60 MHz / 8) =7500000  baud
36.    - Maximum BaudRate that can  beachieved when using the Oversampling by 16
37.      is: (USART APB Clock / 16)
38.  Example: (USART3 APB1 Clock / 16) = (30 MHz /16)  = 1875000 baud
39.  Example: (USART1  APB2 Clock / 16) = (60 MHz /16) = 3750000 baud
40.          - Word Length = 8Bits
41.          - one Stop Bit
42.          - No parity
43.          - Hardware flowcontrol disabled (RTS and  CTS signals)
44.          - Receiveand  transmit enabled
45.     */
46.     USART_InitStructure.USART_BaudRate = 115200;
47.    USART_InitStructure.USART_WordLength=  USART_WordLength_8b;
48.     USART_InitStructure.USART_StopBits =USART_StopBits_1;
49.    USART_InitStructure.USART_Parity=  USART_Parity_No;
50.    USART_InitStructure.USART_HardwareFlowControl=  USART_HardwareFlowControl_None;
51.     USART_InitStructure.USART_Mode =USART_Mode_Rx | USART_Mode_Tx;
52.    USART_Init(USART3,  &USART_InitStructure);
53.   
54.  /*  DMA_Configuration */
55.     DMA_DeInit(DMA1_Stream1);
56.     
57.    DMA_InitStruct.DMA_Channel=  DMA_Channel_4;   
58.     DMA_InitStruct.DMA_PeripheralBaseAddr=  (u32)&USART3->DR; //source  buf
59.     DMA_InitStruct.DMA_Memory0BaseAddr =(u8)pdata; //target buf
60.   
61.    DMA_InitStruct.DMA_DIR=  DMA_DIR_PeripheralToMemory;
62.     DMA_InitStruct.DMA_BufferSize =lenght;  //BuffSize;
63.    DMA_InitStruct.DMA_PeripheralInc=  DMA_PeripheralInc_Disable;
64.     DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
65.    DMA_InitStruct.DMA_PeripheralDataSize =  DMA_PeripheralDataSize_Word;
66.     DMA_InitStruct.DMA_MemoryDataSize=  DMA_MemoryDataSize_Byte;
67.    DMA_InitStruct.DMA_Mode =DMA_Mode_Circular;  //DMA_Mode_Normal;
68.     DMA_InitStruct.DMA_Priority = DMA_Priority_High;
69.    DMA_InitStruct.DMA_FIFOMode=  DMA_FIFOMode_Disable;
70.     DMA_InitStruct.DMA_FIFOThreshold =DMA_FIFOThreshold_HalfFull;
71.    DMA_InitStruct.DMA_MemoryBurst=  DMA_MemoryBurst_Single;
72.     DMA_InitStruct.DMA_PeripheralBurst =DMA_PeripheralBurst_Single;
73.    DMA_Init(DMA1_Stream1,  &DMA_InitStruct);
74.   
75.    /* NVIC configuration  */
76.    /* Configure the Priority  Group to2 bits */
77.    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
78.   
79.     /* Enable the USARTx Interrupt */
80.    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream1_IRQn;  
81.    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
82.    NVIC_InitStructure.NVIC_IRQChannelSubPriority=  0;
83.     NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
84.    NVIC_Init(&NVIC_InitStructure);  
85.   
86.    /* Open DMA  interrupt*/
87.     DMA_ITConfig(DMA1_Stream1, DMA_IT_TC,ENABLE);
88.    DMA_Cmd(DMA1_Stream1, ENABLE);
89.    USART_Cmd(USART3, ENABLE);
90.     USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE);
91.  }
复制代码


DMA中断服务程序如下:
1.    voidDMA1_Stream1_IRQHandler(void) //UART3_RX
2.    {
3.        static short i;
4.     
5.        //Whena  Transfer Complete
6.    if(SET==  DMA_GetITStatus(DMA1_Stream1, DMA_IT_TCIF1))
7.    {
8.    DMA_ClearITPendingBit(DMA1_Stream1,DMA_IT_TCIF1);
9.    i++;
10.  }
11.  }
复制代码


上面程序只配了DMA接收,发送类似。

三、实现DMX512协议DMX512 协议是美国剧场技术协会( United States Institute for TheaterTechnology,  USITT) 制定的数字多路复用协议, 其制定的初衷是为了使舞台、剧场等地所使用的众多的调光器和控制器能相互兼容。虽然它不是一个行业或国家标准, 但是由于它的简单性和实用性, 自从出台以来, 得到了世界各地生产商和使用者普遍承认,这个协议在LED控制方面应用很广泛,利用STM32 USART可以高速传输的特性,我们很容易用STM32来实现DMX512协议。(1)数据的格式及传输DMX512  协议规定数据以数据包的形式通过异步通讯的方式进行传输。每个数据包由若干数据帧组成, 每帧数据包括1 位低电平起始位、8 位数据位和2 位高电平停止位。DMX 协议要求数据传输的波特率为250kb/s, 亦即每位的传输时间为4us, 每帧数据的传输时间为44us, 它支持多达512 帧数据传输, 每帧数据与相应的控制支路相对应。数据包的传送要符合一定的格式和时序要求。为了使接收器能够分辨出第一帧数据, 每一个数据包以一个不短于88us 的低电平信号为起始信号, 即所谓的“Break”信号, 接收器接收到“Break”信号就准备接受随后而来的数据帧; 紧接着“Break”信号之后是不短于8us 的高电平信号M. a. b ( Mark after  Break) ; 之后就是数据帧。在DMX512 协议中, M. a. b 之后的第一帧数据被称为“Star-t code”, 在协议中规定其为零, 但在实际应用中可以由生产厂家自己确定其具体的值,  以传递特殊消息。“Star-t  code”标明其后面的数据是8  位控制信号数据帧。数据帧之间可以有时间间隔, 也可以没有;  同样, 数据包之间可以有时间间隔, 也可以没有。DMX512 协议规定“Break”信号、M. a. b 信号的最短时间, 并规定“Break”信号、M. a. b 信号、数据帧之间及数据包之间的时间间隔的最大值不得超过1s, 否则做出错处理, 但是DMX512 协议并未对出错处理做任何规定。为了严格实现DMX512  数据的时序要求,“Break”和M.  a. b信号我们可以用定时器来实现。具体的UART配置如下:  
1.    USART_InitStructure.USART_BaudRate=  250000;
2.      USART_InitStructure.USART_WordLength = USART_WordLength_8b;
3.      USART_InitStructure.USART_StopBits=  USART_StopBits_2;
4.      USART_InitStructure.USART_Parity = USART_Parity_No;
5.      USART_InitStructure.USART_HardwareFlowControl=  USART_HardwareFlowControl_None;
6.      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
7.      USART_Init(USART1,  &USART_InitStructure);
复制代码




发送DMX512信号过程如下,先把UART的TX脚配置为普通的GPIO并输出低电平,然后启动定时器计时88us,  时器到后把TX脚置为高电平并计时8us, 时器到了后在配为UART模式用DMA方式把数据发出。DMX512信号的接收是个难点,一般直接配为UART接收就行,不需要在UART模式和GPIO模式间切换,但需要在接收过程中检查接收到“Break”信号时的状态是有帧错误出现,并且接收数据全为零,这样的话可以确认已经收到“Break”信号,随后数据正常DMA接收就行了。


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:662810 发表于 2019-12-12 22:28 | 只看该作者
开发STMf407的集成环境是什么
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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