STM32F4 SPI RX/TX DMA 读写FLASH数据

2023-05-16

STM32 使用DMA读写FLASH数据需要注意以下几点:

1.SPI全双工模式下,无论读写FLASH数据均需要同时使能RX/TX DMA。

2.写数据时回读数据应当丢弃,读数据时应当发送0xff来启动SPI读周期。

3.使用DMA时应当使能DMA Stream,然后再使能SPI DMA请求。

 

以下为测试代码,为省事,没启动串口提供打印信息,可在读出FLASH数据后通过断点查看数据。

#include <stdbool.h>
#include <stm32f4xx_dma.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_spi.h>

#define FLASH_PAGE_SIZE            256

static volatile int g_rx_flag = 0;
static volatile int g_tx_flag = 0;

static void spi_wait_rx(void)
{
   while(!g_rx_flag);
   g_rx_flag = 0;
}

static void spi_post_rx(void)
{
   g_rx_flag = 1;
}


static void spi_wait_tx(void)
{
   while(!g_tx_flag);
   g_tx_flag = 0;
}

static void spi_post_tx(void)
{
   g_tx_flag = 1;
}

static void spi_do_delay(uint16_t n)
{ 
  uint16_t t = n;
  while (-- t);
}

uint8_t spi_byte_transfer(uint8_t Dat)
{
  while ((SPI3->SR & SPI_I2S_FLAG_TXE) == 0);
  SPI3->DR = Dat;
  while ((SPI3->SR & SPI_I2S_FLAG_RXNE) == 0);
  return ((uint8_t)(SPI3->DR));
}

uint8_t spi_readbyte(void)
{
  return spi_byte_transfer(0xA5);
}

/* 使用 GPIO6 作为 CS 信号
 */
static void spi_chip_select(bool select)
{
    spi_do_delay(5);
    
    if (select == true)
    {
        GPIOB->BSRRH = GPIO_Pin_6;
    }
    else
    {
        GPIOB->BSRRL = GPIO_Pin_6;
    }
    
    spi_do_delay(5);
}

void flash_wait_write(void)
{
  uint8_t status = 0;
  
  spi_chip_select(true);
  spi_byte_transfer(0x05);
  do
  {
    status = spi_byte_transfer(0xA5);
  } while (status & 0x01);
  
  spi_chip_select(false);
}

void flash_enable_write(void)
{
  spi_chip_select(true);
  spi_byte_transfer(0x06);
  spi_chip_select(false);
}

void flash_write_status(uint8_t value)
{
  flash_enable_write();
  
  spi_chip_select(true);
  spi_byte_transfer(0x01);
  spi_byte_transfer(value);
  
  spi_chip_select(false);
  
  flash_wait_write();
}

void flash_disable_write(void)
{
  flash_write_status(0);
}

uint32_t flash_read_identify(void)
{
  uint8_t byte0 = 0, byte1 = 0, byte2 = 0;
  
  spi_chip_select(true);
  
  spi_byte_transfer(0x9F);
  byte0 = spi_byte_transfer(0xA5);
  byte1 = spi_byte_transfer(0xA5);
  byte2 = spi_byte_transfer(0xA5);
  
  spi_chip_select(false);
  
  return ((byte0 << 16) | (byte1 << 8) | (byte2 << 0));
}

void flash_erase_sector(uint32_t SectorAddr)
{
  flash_enable_write();
  
  spi_chip_select(true);
  spi_byte_transfer(0x20);
  spi_byte_transfer((SectorAddr >> 16) & 0xFF);
  spi_byte_transfer((SectorAddr >>  8) & 0xFF);
  spi_byte_transfer((SectorAddr >>  0) & 0xFF);
  spi_chip_select(false);
  
  flash_wait_write();
}

/**
 * 启动SPI DMA通道
 * buffer      缓冲区指针
 * length      缓冲区数据长度,
 *             如果 isread = true 表示需要从 flash 中读取多少个字节。
 *             如果 isread = false 表示需要向 flash 写入多少个字节。
 * isread      true = 读,false = 写
 * 
 */
void flash_start_dma(uint8_t *buffer, uint32_t length, uint8_t isread)
{
    uint32_t temp = 0xffffffff;
    DMA_InitTypeDef DMA_InitStructure;

    
    DMA_StructInit(&DMA_InitStructure);
    DMA_DeInit(DMA1_Stream0);
    DMA_DeInit(DMA1_Stream7);
    while(DMA_GetCmdStatus(DMA1_Stream0) != DISABLE);
    while(DMA_GetCmdStatus(DMA1_Stream7) != DISABLE);

    /* DMA1 channel 0 stream0 --- 配置 SPI3-RX DMA */
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI3->DR;
    
    if (isread == true)
    {
        /* 读方式下回读数据放到 buffer 中*/
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    }
    else
    {
        /* 写方式下回读数据丢弃 */
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&temp;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
    }

    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize = length;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA1_Stream0, &DMA_InitStructure);
    
    /* DMA1 channel 0 stream7 --- 配置 SPI3-TX DMA */
    DMA_StructInit(&DMA_InitStructure);
    
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI3->DR;

    if (isread == true)
    {
        /* 读方式下发送 0xff */
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&temp;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
    }
    else
    {
        /* 写方式下发送 buffer 数据*/
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    }
    
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_BufferSize = length;  
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA1_Stream7, &DMA_InitStructure);

    /* 1.开启 DMA 数据流传输完成中断 */
    DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, ENABLE);
    DMA_ITConfig(DMA1_Stream7, DMA_IT_TC, ENABLE);

    /* 2.使能 DMA 数据流 */
    DMA_Cmd(DMA1_Stream0, ENABLE);
    DMA_Cmd(DMA1_Stream7, ENABLE);

    /* 3.使能 SPI DMA 请求 */
    SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Rx|SPI_I2S_DMAReq_Tx, ENABLE);

    /* 5.等待 DMA 传输完成 */
    spi_wait_tx();
    spi_wait_rx();
}

void DMA1_Stream7_IRQHandler(void)
{
    if (DMA_GetFlagStatus(DMA1_Stream7, DMA_FLAG_TCIF7) != RESET)
    {
        /* 1.清中断标志 */
        DMA_ClearFlag(DMA1_Stream7, DMA_FLAG_TCIF7);
        /* 2.禁能 DMA   传输完成中断 */
        DMA_ITConfig(DMA1_Stream7, DMA_IT_TC, DISABLE);
        /* 3.禁能 SPI TX DMA   请求 */
        SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, DISABLE);
        /* 4.禁能 DMA Stream */
        DMA_Cmd(DMA1_Stream7, DISABLE);
        /* 5.通知应用程序 TX 传输完成 */
        spi_post_tx();
    }
}

void DMA1_Stream0_IRQHandler(void)
{
    if (DMA_GetFlagStatus(DMA1_Stream0, DMA_FLAG_TCIF0) != RESET)
    {
        /* 1.清中断标志 */
        DMA_ClearFlag(DMA1_Stream0, DMA_FLAG_TCIF0);
        /* 2.禁能 DMA   传输完成中断 */
        DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, DISABLE);
        /* 3.禁能 SPI TX DMA   请求 */
        SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Rx, DISABLE);
        /* 4.禁能 DMA Stream */
        DMA_Cmd(DMA1_Stream0, DISABLE); 
        /* 6.通知应用程序 RX 传输完成 */
        spi_post_rx();
    }
}

void flash_write_page(uint8_t* buffer, uint32_t addr)
{
  flash_enable_write();
  
  spi_chip_select(true);
  spi_byte_transfer(0x02);
  spi_byte_transfer((addr >> 16) & 0xFF);
  spi_byte_transfer((addr >>  8) & 0xFF);
  spi_byte_transfer((addr >>  0) & 0xFF);

  flash_start_dma(buffer, FLASH_PAGE_SIZE, false);

  spi_chip_select(false);
  flash_wait_write();
}

void flash_read_page(uint8_t *buffer, uint32_t addr)
{
    spi_chip_select(true);
    spi_byte_transfer(0x03);
    spi_byte_transfer((addr >> 16) & 0xFF);
    spi_byte_transfer((addr >>  8) & 0xFF);
    spi_byte_transfer((addr >>  0) & 0xFF);

    flash_start_dma(buffer, FLASH_PAGE_SIZE, true);
    spi_chip_select(false);
}


void flash_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

    SPI_InitTypeDef  SPI_InitStructure;  
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI3);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI3);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI3);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_4;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI3, &SPI_InitStructure);
    SPI_Cmd(SPI3, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream7_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream0_IRQn;
    NVIC_Init(&NVIC_InitStructure);

    spi_chip_select(false);
}


uint8_t wbuffer[512];
uint8_t rbuffer[512];

int main(void)
{
    int i = 0;
    
    flash_init();

    /* 初始化测试数据 */
    for (i = 0; i < 512; i++)
    {
        wbuffer[i] = (uint8_t)(i+9);
    }

    flash_erase_sector(0);
    flash_read_page(rbuffer, 0);    /* 在此处打断点查看数据 */
    flash_write_page(wbuffer, 0);
    flash_read_page(rbuffer, 0);    /* 在此处打断点查看数据 */

    while(1);
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F4 SPI RX/TX DMA 读写FLASH数据 的相关文章

  • 将外部 png 加载到 AS2 swf 中,该 AS2 swf 加载到 AS3 swf 包装器中

    我有一个 Wrapper SWF 可以加载一系列 AS2 电影 每个 AS2 影片都会加载一系列 png 文件 AS3 wrapper swf gt AS2 1 swf gt image 1 png gt image 2 png gt AS
  • Flash / Java Applet 的 NPAPI 插件替代方案

    我的问题是关于 2014 年 12 月后 chrome 宣布不支持 NPAPI 插件 Firefox 也遵循同样的规定 我的一个旧应用程序中有一个基于 NPAPI 的插件 到目前为止该插件运行良好 但在 Chrome 和 Firefox 发
  • 我有两个类型定义,如何确定一个类型是否是另一个的基类型?

    我在 ActionScript 3 中有两个类型定义 Class 类型的引用 我需要确定其中一个是否是另一个的基类型 类或接口 我本来希望像下面这样的东西会起作用 但遗憾的是它没有 var isBaseClass Boolean Mouse
  • Html5 视频和 Flash 方法

    研究 HTML5 视频标签 并研究哪些浏览器支持哪些视频文件类型 我最初的想法是事情变得比仅仅使用 Flash 更困难 我想知道是否有人已经找到一些骨架代码 与视频的开发方法相结合 来执行以下操作 如果闪光灯可用 请使用它 如果没有 请尝试
  • AsyncTask 也在 flash 中吗?

    我开发了一款大小为 27mb 的游戏 我将其加载到设备中 它的性能会降低 有时会挂起设备 这个游戏中使用了很多媒体资源 如果我在 android 中制作它 那么我会处理和异步任务 http developer android com ref
  • 在 ActionScript 中移动数组中的对象,产生体育场波浪效果

    我想移动数组中的所有对象 产生体育场波浪效果 我想根据舞台上的 y 值移动对象 我所有的方块大小都是 50x50 我想将它们向上移动然后向下移动 下面是我的代码 import fl transitions Tween import fl t
  • 在 ARM 处理器上执行存储在外部 SPI 闪存中的程序

    我有一个 ARM 处理器 能够与外部闪存芯片连接 写入芯片的是为 ARM 架构编译的程序 可供执行 我需要知道如何将这些数据从外部闪存获取到 ARM 处理器上以供执行 我可以提前运行某种复制例程 将数据复制到可执行内存空间吗 我想我可以 但
  • SWFUpload 还活着吗?

    我正在考虑在我的网站上使用 SWFUpload 但我看到最后一个版本是在 2010 年 3 月 而且它还是一个测试版 看起来 SWFUpload 的开发就停止了 这个项目还活着吗 还有其他选择吗 在我看来 SWF上传看起来很死 自 2010
  • 使用flash动作脚本开发网络游戏

    简而言之 如果我想使用 Flash 技术开发在线游戏 你能告诉我一些很好的学习资源吗 包括3D游戏 您可以从新发布的开始Flash平台游戏技术中心 http www adobe com devnet games 在 Adob e Devne
  • 在 Android Flash 10.1 上打开软件键盘

    我正在开发在浏览器中运行的移动 Flash 应用程序 不是 AIR 应用程序 根据 Adob e 的说法 Flash Player 10 1 提供支持 使用本机设备虚拟键盘 如果没有物理支持 则使用 TextField 支持 检测到键盘 一
  • 使用 Actionscript 3 连接到数据库 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在寻找有关如何基于数据库在 Flash 中动态创建内容的建议 最初我想将数据库导出到 XML 文件并使用内置的 Actionscr
  • 如何在多个 HTML 页面上播放背景音频?

    是否有解决方案可以让背景音频 音乐在网站上的多个页面上播放 而无需在每个页面加载时重新启动 该网站当前使用框架集 但我正在寻找替代方案 如果不让整个网站都 AJAX 我认为框架是唯一的方法 如果您需要的话 这里有一个关于制作 ajax 站点
  • 在 Flash AS3 中捕获未处理的 IOErrorEvent

    错误 2044 未处理的 IOErrorEvent text 错误 2036 从不加载 完全的 这就是我每次尝试使用加载器加载不存在的图像时看到的情况 我正在获取 URL 列表 但无法验证它们是否指向任何有用的内容 每当遇到 404 时 它
  • 如何调整外部 SWF 的大小以适合容器?

    我想要完成的是调整外部 SWF 的大小 使其适合在舞台上作为容器呈现的显示对象 现在它显示在容器外部 重要提示 我不希望外部 SWF 占据整个舞台 我在舞台上为它准备了一个特殊的地方 那个容器 public function loaderC
  • 有没有办法覆盖动作脚本运算符,特别是我想覆盖等于运算符

    是否可以覆盖 equals 运算符 即 对于可以通过 2 个或更多字段匹配来确定相等性的客户类别 如果您的意思是重载 作为 equals 的同义词 那么您不能 因为 ActionScript 不提供运算符重载 只需为您的类编写一个 equa
  • Chrome 更新阻止 Flash 自动播放 - 如何避免?

    我在 html 页面中嵌入了 YouTube 视频 我将 youtube iframe API 与 Flash 结合使用 在我的例子中 我无法使用 HTML5 视频 自上次 Google Chrome 更新以来 Chrome 会阻止自动播放
  • 推荐一个适用于 Flex 和 AIR 的 HTML 友好的 RichTextEditor? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在 PhantomJS 中使用 JavaScript 检测网页上的声音?

    我需要检测带有横幅的网页中的所有声音 我怎样才能做到这一点 我查看 PhantomJS 但找不到浏览器声音的 API PhantomJS 1 x 和 2 不支持 Flash
  • 更改 AS3 中的 TextField 选择颜色

    如何更改 ActionScript 3 中 TextField 的选择 突出显示 颜色 我有一个输入文本字段 黑色背景上有白色文本 因此 选择是不可见的 这对于可用性来说非常糟糕 谢谢 另一种方法是使用文本布局框架 特别是使用 Select
  • Adobe Flash 项目的版本控制

    我正在处理一个非常复杂的 Flash 项目 该项目是我们为客户使用而部署的全套服务的一部分 对于我们的大多数软件源 Java PHP Javascript HTML 和一些其他语言的支持脚本 我们使用 subversion 进行版本控制和管

随机推荐

  • Types of daTabases数据库类型

    NoSQL databases provide the performance scalability and stability that s required by the modern data driven apps we inte
  • jeston TX1_TX2 ubuntu18.04安装(国内安装源gitee)ROS Melodic

    查看ubunut系统信息 cat proc version uname a lsb release a 我自己的系统信息是 xff1a 由于我自己已经迁移了系统至SD卡 xff0c 所以存储比较富裕 xff1a 通过对应的ubuntu版本安
  • 9 个将改变一切的物联网应用

    无论您是有远见的 CEO 技术驱动型 CEO 还是 IT 领导者 xff0c 您之前都遇到过 IoT 一词 它经常与最高级一起使用 xff0c 表示它将如何彻底改变您的工作 娱乐和生活方式 但这只是另一个流行语 xff0c 还是承诺的技术圣
  • Android aplog是什么?

    aplog 是系统应用层的log xff0c 比如应用程序无响应或强行关闭 xff0c kernel相关的 xff0c 比如driver xff08 相机 蓝牙 usb 启动 xff09 出了开机问题 手机对服务唤醒和休眠的一些记录蓝牙相关
  • android 7.0 加入 android:directBootAware

    Android N引入了一个新特性 xff1a Direct Boot Mode 设备启动后进入的一个新模式 xff0c 直到用户解锁 xff08 unlock xff09 设备此阶段结束 在此 Direct Boot Mode 下 APP
  • Kotlin概述与Java的比较

    Kotlin是JetBrains的一种新的编程语言 它首次出现在2011年 xff0c JetBrains推出了名为 科特林 的项目 Kotlin是开源语言 基本上像Java一样 xff0c C和C 43 43 Kotlin也是 静态类型编
  • armlink 用法详解

    映像文件 image xff1a 是指一个可执行文件 xff0c 在执行的时候被加载到处理器中 一个映像文件有多个线程 它是ELF Executable and linking format 格式的 段 Section xff1a 描述映像
  • 人工智能的五大核心技术

    计算机视觉 机器学习 自然语言处理 机器人和语音识别是人工智能的五大核心技术 xff0c 它们均会成为独立的子产业 计算机视觉 计算机视觉是指计算机从图像中识别出物体 场景和活动的能力 计算机视觉技术运用由图像处理操作及其他技术所组成的序列
  • ubuntu下文件拷贝命令cp命令

    该命令的功能是将给出的文件或目录拷贝到另一文件或目录中 xff0c 就如同DOS下的copy命令一样 xff0c 功能非常强大 语法 xff1a cp xff3b 选项 xff3d 源文件或目录 目标文件或目录 说明 xff1a 该命令把指
  • android camera 照相机/摄像机

    一 camera启动 1 一个activity启动调用流程 xff1a onCreate gt onStart gt onResume onCreate xff1a 1 可添加所需布局文件 xff0c 画界面 2 开启线程 xff0c 启动
  • 正确学习javascript。困惑的指南

    正确学习 javascript 困惑的指南 迷失了 javascript xff1f 这一点都不奇怪 你需要一个能告诉你真正重要的指南 我们只有一个 向左看 有一个框架市场 xff0c 它们相互竞争 xff0c 赞扬它们的能力 向右看 这是
  • 【ROS学习2】创建ROS工作空间及功能包

    目录 创建ROS工作空间及功能包工作空间 workspace src 代码空间 Source Space build 编译空间 Build Space devel 开发空间 Development Space install 安装空间 In
  • 【GStreamer 】5-5-总结USB相机转RTSP网络视频流-推流usb摄像头JPEG

    我们使用gstreamer rtsp server xff0c 实现了USB相机转RTSP网络流的基本功能 xff0c 之前很多篇都讲了如何实现 xff0c 这一次我们集中精力解决之前的一些问题 文章 GStreamer 5 4 USB相机
  • C程序设计语言 5-3

    练习5 3 用指针方式实现第2章中的函数strcat 函数strcat s t 将t指向的字符串复制到s指向的字符串的尾部 include lt stdio h gt int my strcat char char int main cha
  • NuttX 文件系统架构介绍(7.14)

  • 谈谈memcpy函数的优化(纯C)

    在使用C语言编程时 xff0c 我们常用memcpy来复制内存数据 xff0c 但很少有人会关注到memcpy怎么实现 最简单的memcpy功能实现如下 xff1a void low memcpy void dst const void s
  • USB DEVICE调试心得

    一 USB设备链接后无法HUB不上报发现新设备 USB控制器未打开 xff0c USB DP DM引脚配置不正确 二 能够发现设备 xff0c 但HOST端提示获取描述符失败 获取描述符是 USB DEVICE 链接后 HOST 向 DEV
  • PX4uORB介绍[4]-对象和数据结构

  • ubuntu禁止显示器休眠的方法

    近期在firefly RK3399开发板上调试代码 xff0c 经常遇到显示器自动休眠 xff0c 并且发现每次休眠都对系统实时性产生一些影响 xff0c 最终在万能的CSDN博客上找到解决办法 xff1a Linux不让显示器休眠的方法
  • STM32F4 SPI RX/TX DMA 读写FLASH数据

    STM32 使用DMA读写FLASH数据需要注意以下几点 xff1a 1 SPI全双工模式下 xff0c 无论读写FLASH数据均需要同时使能RX TX DMA 2 写数据时回读数据应当丢弃 xff0c 读数据时应当发送0xff来启动SPI