2021-3-9-3月份日志

发布时间 2023-09-17 19:47:06作者: Yecgaa1

layout: post
title: 3月份日志
categories: 日志
tags: 
    - 开发 
    - 日志
BGImage: 'https://github.xutongxin.me/https://raw.githubusercontent.com/xutongxin1/PictureBed/master/img0/202020210312152426.png'
jekyll-theme-WuK:
    musicid: '526464671'

3.9

继续开工

先弄弄DMA

(uint8_t *)t

将变量类型强制转换为uint8 *类型

volatile uint8_t rx_len ;  //接收一帧数据的长度

volatile关键词影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,以免出错

USART的中断类型比你想象的要多

UART_IT_CTS:CTS更改中断

UART_IT_LBD:LIN中断检测中断

UART_IT_TXE:发送数据寄存器为空中断

UART_IT_TC:发送完成中断

UART_IT_RXNE:接收数据寄存器不为空中断

UART_IT_IDLE:空闲线检测中断(接收完之后的中断等,一般不会触发)

UART_IT_PE:奇偶校验错误中断

UART_IT_ERR:错误中断(帧错误,噪声错误,溢出错误)

开启语句

__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //启动IDLE中断

全局变量办法

在一个头文件先定义

//user.h
#ifndef DMA_USER_H
#define DMA_USER_H

extern uint8_t  rx_buffer[100];
#endif //DMA_USER_H

然后在main.c的main()外面声明

//main.h
//需要先#include "user.h"
/* USER CODE BEGIN PV */
uint8_t  rx_buffer[100];
/* USER CODE END PV */

然后该项目所有文件直接引用user.h即可

3.15

3.11

USART串口几个中断的问题

接收有两种方案,中断来接收和DMA转存

前者使用

//HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size),如
HAL_UART_Receive_IT(&huart1,(uint8_t *)&value,1);   //中断接收一个字符,存储到value中

这句话不仅定义了要收个数据去pData里,还定义了要收到一个一个字符就中断一次(后台),并且存到pData,直到存了Size个字符,结束中断转存,进入回调函数

HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //串口接收中断回调函数

这里的逻辑有些复杂,再详细说说

比如我现在有100个字符

我打开了

HAL_UART_Receive_IT(&huart1,(uint8_t *)&value,20);//只要20个

收到第一个就会进入

HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //串口中断处理函数

然后存到value里去,然后算算数,才收了一个还没到20个呢,然后继续等着下一个

等到20个字符了,不会再进HAL_UART_IRQHandler中断的同时,进入HAL_UART_RxCpltCallback回调函数,记住,此时HAL_UART_Receive_IT已经完成了,所以要继续收剩下80个记得开回来。

和HAL_UART_RxCpltCallback类似的回调函数有以下函数

HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);  //串口发送中断回调函数
HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);  //串口发送一半中断回调函数(用的较少)
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);  //串口接收中断回调函数
HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//串口接收一半回调函数(用的较少)
HAL_UART_ErrorCallback();//串口接收错误函数

但是每次都进中断并不太好,性能不是最优的,所以有了DMA

DMA是啥不说了,DMA需要配置

HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

还是把数据放进pData,然后收Size个数据

但是不同的是这个不经过中断,因此更快占用更小

先附上和DMA有关的函数

HAL_UART_Transmit_DMA();//串口DMA模式发送
HAL_UART_Transmit_DMA();//串口DMA模式接收
HAL_UART_DMAPause() //暂停串口DMA
HAL_UART_DMAResume(); //恢复串口DMA
HAL_UART_DMAStop();// 结束串口DMA

突然又有个问题了,如果我不确定我要收多少怎么办

第一种不用DMA的老办法

HAL_UART_Receive_IT(&huart1,(uint8_t *)&value,1);   //每次收一个!

然后在中断里等待自己设置的终止符

这个方法慢,所以有了第二种

等待串口接收到东西后的休息时间

先在main.h初始化变量

volatile uint8_t rx_len = 0;             //接收一帧数据的长度
volatile uint8_t recv_end_flag = 0;    //一帧数据接收完成标志
uint8_t rx_buffer[200]={0};   //接收数据缓存
#define BUFFER_SIZE 255

修改static void MX_USART1_UART_Init(void)函数,或者在main.c里添加

//main.c
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //启动串口收完数据后的闲时中断(开了自己不会默认停下)
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//打开第一次接收

然后跳进

//stm32f1xx_it.c中
void USART1_IRQHandler(void);

如果你是开HAL_UART_Receive_IT,其实每个数据转存都会进来这里

然后你要做的就是加多这个函数内要干的事情

void USART1_IRQHandler(void)
{
      /* USER CODE BEGIN USART1_IRQn 0 */
	uint32_t tmp_flag = 0;
    uint32_t temp;
    /* USER CODE END USART1_IRQn 0 */
    
  HAL_UART_IRQHandler(&huart1);//这段默认就在这里了,不要删去
    //最好上面的逻辑也换个地方写
    
  /* USER CODE BEGIN USART1_IRQn 1 */
tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
	if((tmp_flag != RESET))//idle标志还在,串口没有突然又干活了
	{ 
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
        //HAL_UART_DMAStop(&huart2); //先暂停
        //temp = __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);// 获取DMA中未传输的数据个
        //rx_len = BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个
        //recv_end_flag=1;//引入flag方便主while处理数据
		//DO What You Want To DO
       HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重置size的计数!
	 }
  /* USER CODE END USART1_IRQn 1 */
}

最后是DMA发送

 HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

其他的发送虽然从此看不上了,但还是记录一下

HAL_UART_Transmit();//串口发送数据,使用超时管理机制
HAL_UART_Receive();//串口接收数据,使用超时管理机制
HAL_UART_Transmit_IT();//串口中断模式发送
HAL_UART_Receive_IT();//串口中断模式接收

最后还看到个有意思的代码

    
 /* * 函数功能: 重定向c库函数printf到DEBUG_USARTx
    * 输入参数: 无
    * 返 回 值: 无
    * 说    明:无
    */
        int fputc(int ch, FILE *f)
        {
          HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
          return ch;
        }
    
    /**
    
      * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
      * 输入参数: 无
      * 返 回 值: 无
      * 说    明:无
        */
        int fgetc(FILE *f)
        {
          uint8_t ch = 0;
          HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
          return ch;
        }

两个没有用DMA的,但是还是可以的

尝试造esp8266的无线调试器,模块用的是Esp-wroom-02d,记录几个点

  1. EN脚理论上其实不是直接上电,而是加一个延时电路

  2. 烧录时GPIO15和GPIO0都要拉低,但是运行时GPIO0置空,GPIO15似乎还是要拉低

  3. 烧录命令可以在构建完之后看到,GUI版本的烧录器没有验证(Flash容量没得选)

    如:python "C:\Users\xtx\OneDrive - xutongxin\ESP8266\DAP\pytool\esptool\esptool.py" -p COM16 -b 921600 --after hard_reset write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 bootloader.bin 0x8000 partition-table.bin 0x10000 esp8266_dap.bin

  4. esptool可以直接用rtos-sdk里的,pip直接安装不太好用。同时要先装pip install pyserical

  5. bootloader.bin和partition-table.bin也在rtos-sdk里,直接在Github Action提取出来即可

然后是Github Action功能,就是在线构建功能

  1. 如果直接按着main.yml对着ubuntu虚拟机这样做是不行的,所以不能线下复现
  2. 提取出文件的方案(记得重新校对排版),然后在action界面可以看到
 - name: Deliver firmware

   uses: actions/upload-artifact@v2

   with:

     name: pytool

     path: ./ESP8266_RTOS_SDK/components/esptool_py



 - name: Deliver firmware1

   uses: actions/upload-artifact@v2

   with:

​    name: pytool2

​    path: ./idf.py


至于利用发布功能提取文件就算了吧