百科问答小站 logo
百科问答小站 font logo



为什么网上连开源的stm32 8个串口程序都没有? 第1页

  

user avatar   zhang-hao-72 网友的相关建议: 
      

分享个我的, 任意个串口, 你按你的需求改改就行了. 我已经在N个项目里用过了.

字符中断方式接收, 空闲中断判断帧尾, 阻塞方式发送. 哪位有兴趣了可以试试加上中断方式发送, 这样CPU负担轻一些. 不用DMA是因为串口多了没有那么多DMA通道用, 就算够用, SPI/ADC之类也没得用了.

       // 请添加你自己的头文件  #define MAX_LEN 128  // 帧长度, 按你的需要 #define USART_TOTAL_NUM 4          // 串口个数  typedef struct {     const USART_TypeDef* usartx;     unsigned char msg[MAX_LEN];     unsigned char rxbuf[MAX_LEN];               // 用两个缓冲区, 进入后处理函数后接收缓冲区就可以用于新一轮接收, 只是比较浪费内存     unsigned char* rxptr;     int size, updated; } usartx_t;  static struct {     usartx_t usart[USART_TOTAL_NUM];     void (*parser_f)(const void* msg, int size, int source);           // 后处理函数指针, 用source区分是哪个串口 } g;  void USART_BindParser(void (*parser_f)(const void* msg, int size, int source))    // 初始化串口后用它绑定你自己的回调函数做进一步处理 {     g.parser_f = parser_f; }  void USART_ReConfig(USART_TypeDef* USARTx, unsigned long baudrate) {     USART_InitTypeDef uis; //    USART_DeInit(USARTx);     USART_Cmd(USARTx, DISABLE);     USART_StructInit(&uis);     uis.USART_WordLength = USART_WordLength_8b;     uis.USART_StopBits = USART_StopBits_1;     uis.USART_Parity = USART_Parity_No;     uis.USART_HardwareFlowControl = USART_HardwareFlowControl_None;     uis.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;     uis.USART_BaudRate = baudrate;     USART_Init(USARTx, &uis); //    if(USARTx == USART1) //        USART_SWAPPinCmd(USARTx, ENABLE);              // 根据你的需求, 交换串口的tx/rx脚, 只在f0和f3系列有效     USART_Cmd(USARTx, ENABLE);     USART_ITConfig(USARTx, USART_IT_IDLE, ENABLE);     USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);     USART_ITConfig(USARTx, USART_IT_ORE, ENABLE);     USART_ITConfig(USARTx, USART_IT_FE, ENABLE); }  void USART_Config(void) {     NVIC_InitTypeDef nis;      RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);     RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE); //    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);      nis.NVIC_IRQChannel = USART1_IRQn;     nis.NVIC_IRQChannelPreemptionPriority = 1;     nis.NVIC_IRQChannelSubPriority = 1;     nis.NVIC_IRQChannelCmd = ENABLE;     NVIC_Init(&nis);     nis.NVIC_IRQChannel = UART5_IRQn;     NVIC_Init(&nis);      for(int i = 0; i < USART_TOTAL_NUM; i++) {         g.usart[i].rxptr = g.usart[i].rxbuf;         g.usart[i].size = 0;         g.usart[i].updated = 0;     }     g.usart[0].usartx = USART1;     g.usart[1].usartx = USART2;     g.usart[2].usartx = USART3;     g.usart[3].usartx = UART4; //    g.usart[4].usartx = UART5;      USART_ReConfig(USART1, 500000UL);              // 依次初始化你需要的串口 //    USART_ReConfig(UART5, 500000UL); }  void USART_WriteData(USART_TypeDef* USARTx, const void* data, int num)        // 阻塞方式, 中断方式自己写吧. DMA方式虽然好但是没那么多通道 {     while(num--) {         while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);         USART_SendData(USARTx, *((unsigned char*)data));         data++;     }     while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET); }  void USART_WriteByte(USART_TypeDef* USARTx, unsigned char byte)            // 一般用不到, 有些库可能需要单字节发送函数 {     USART_WriteData(USARTx, &byte, 1); }  void USART_Poll(void)               // 在主循环里调用, 不要放在中断里 {     for(int i = 0; i < USART_TOTAL_NUM; i++) {         usartx_t* p = &(g.usart[i]);         if(p->updated) {             g.parser_f(p->msg, p->size, i);              // 在这里调用你自己的回调函数做进一步处理             p->updated = 0;         }     } }  void USART_RXNE_IRQHandler(USART_TypeDef* USARTx)        // 在RXNE中断里调用 {     for(int i = 0; i < USART_TOTAL_NUM; i++) {         usartx_t* p = &(g.usart[i]);         if(USARTx == p->usartx) {             if(p->rxptr - p->rxbuf >= MAX_LEN)                 break;             *(p->rxptr) = p->usartx->RDR;                 // 在F0和F3是RDR, 在F1是DR             p->rxptr++;             break;         }     } }  void USART_IDLE_IRQHandler(USART_TypeDef* USARTx)            // 在IDLE中断里调用 {     for(int i = 0; i < USART_TOTAL_NUM; i++) {         usartx_t* p = &(g.usart[i]);         if(USARTx == p->usartx) {             p->size = p->rxptr - p->rxbuf;             memcpy(p->msg, p->rxbuf, p->size);             p->rxptr = p->rxbuf;             p->updated = 1;             break;         }     } }     




  

相关话题

  自制电视盒子选择stm32还是arduino? 
  8051 6502 avr的好处都有啥? 
  什么是寄存器压栈?栈是内存的一部分,寄存器是cpu一部分,怎么压? 
  能求教STM32动态内存分配如何解决内存碎片问题吗? 
  自制电视盒子选择stm32还是arduino? 
  我现在是一名嵌入式方向的研究生,发现学的东西比做纯软件的多,工资还没他们高,嵌入式的优势到底在哪儿? 
  嵌入式linux内核在内存中运行地址0x30008000到内存起始运行地址0x30000000中的(0x8000=32k)怎么回事? 
  我现在是一名嵌入式方向的研究生,发现学的东西比做纯软件的多,工资还没他们高,嵌入式的优势到底在哪儿? 
  废旧的 Android 手机能拿来干什么有趣的事? 
  国内和国外,对于嵌入式工程师,有哪些权威认证 ? 

前一个讨论
好的医学院和差的医学院有什么区别?
下一个讨论
现在大二,攒了 3 万块钱,想配一台电脑,如何说服爸妈?





© 2024-11-25 - tinynew.org. All Rights Reserved.
© 2024-11-25 - tinynew.org. 保留所有权利