基于循环缓冲区的UART串口发送功能

串口开发之环形缓冲区 串口接收数据长度位置,频率未知,不要求实时处理的场景。缓冲队列来解决在处理的时候来的数据包就“丢失”的问题。 阅读详情

在实际使用时,有些芯片没有提供完整的串口发送库或者使用方法,调试起来比较麻烦需要自己写一个,在此已做记录。

功能:

        基于循环缓冲区实现串口发送,主要用于将数字转换为ASCII字符串并通过串口发送出去

代码:

        

// 定义缓冲区长度为80字节
#define BUFF_LEN 80

// 全局变量声明
unsigned char buff_len;            // 缓冲区中待发送的数据长度
unsigned char dat_out_index;       // 数据发送指针(指向下一个要发送的数据)
unsigned char dat_in_index;        // 数据接收指针(指向下一个要存储的位置)
unsigned char dat_buff[BUFF_LEN];  // 数据循环缓冲区
unsigned char dat_arr[17];         // 临时数组,用于存储数字转换后的ASCII字符
bit f_trig_send;                   // 发送触发标志位(8位单片机,和bool用法相同)

// UART初始化函数
void uart_init(void)
{
    /*需要根据芯片手册做对应的初始化*/    

    /*变量参数初始化*/
    u8buff_len = 0;              // 初始化缓冲区长度为0
    u8dat_out_index = 0;         // 初始化发送指针
    u8dat_in_index = 0;          // 初始化接收指针
    f_trig_send = 0;             // 初始化发送触发标志为0
}

// UART任务处理函数,需要周期性调用
void uart_task(void)
{
    // 如果缓冲区有数据且未触发发送,则触发发送
    if ((buff_len > 0) && (f_trig_send == 0))
    {
        f_trig_send = 1;         // 设置发送触发标志
        //需要修改为对应IC串口发送的寄存器
        UT2_CR |= 0x02;          // 设置UART控制寄存器的发送使能位(假设0x02是发送使能位)
    }

    // 如果缓冲区有数据且UART发送就绪(需要修改为对应IC串口发送的寄存器)
    if (8buff_len > 0) && (UT2_CR & 0x02))
    {
        buff_len--;           // 减少缓冲区待发送数据长度
        //需要修改为对应IC串口发送的寄存器
        UT2_DR = dat_buff[dat_out_index]; // 将数据写入UART数据寄存器
        //需要修改为对应IC串口发送的寄存器
        UT2_CR &= ~0x02;         // 清除发送使能位
        dat_out_index++;       // 移动发送指针
        
        // 处理发送指针回绕
        if (dat_out_index >= BUFF_LEN)
        {
            dat_out_index = 0;
        }
        
        // 如果缓冲区数据已全部发送,清除发送触发标志
        if (buff_len == 0)
        {
            f_trig_send = 0;
        }
    }
}

// UART打印函数,将数字转换为ASCII并存入发送缓冲区
void uart_print(unsigned int dat)
{
    unsigned int dat_tem;     // 临时变量存储输入数据
    unsigned char tem;        // 临时变量
    unsigned char i;          // 循环计数器

    dat_tem = dat;         // 保存输入数据
    
    // 处理输入为0的特殊情况
    if (dat_tem == 0)
    {
        // 处理缓冲区回绕
        if (dat_in_index >= BUFF_LEN)
        {
            dat_in_index = 0;
        }

        // 将'0'存入缓冲区
        dat_buff[u8dat_in_index] = 0 + 0x30; // 0x30是'0'的ASCII码
        dat_in_index++;
        buff_len++;
    }
    else
    {
        i = 0;
        // 将数字逐位分解并转换为ASCII
        while (dat_tem != 0)
        {
            tem = dat_tem % 10;       // 获取最低位数字
            dat_arr[i] = tem + 0x30; // 转换为ASCII存入临时数组
            i++;
            dat_tem /= 10;                // 移除最低位
        }
        buff_len += i;                 // 更新缓冲区长度

        // 将临时数组中的数字按正确顺序存入缓冲区
        while (i)
        {
            // 处理缓冲区回绕
            if (dat_in_index >= BUFF_LEN)
            {
                dat_in_index = 0;
            }
            i--;
            dat_buff[dat_in_index] = dat_arr[i]; // 从高位到低位存入
            dat_in_index++;
        }
    }

    // 在数字后添加换行符(0x0D)
    if (dat_in_index >= BUFF_LEN)
    {
        dat_in_index = 0;
    }
    dat_buff[dat_in_index] = 0x0d; // 换行符(CR)
    dat_in_index++;
    buff_len++;
}

使用方法:

        1、初始化:

                在使用UART功能前,必须先调用初始化函数:

                uart_init();

        2、周期性任务处理:

                需要在主循环中定期调用任务处理函数:

                 

void main (void)
{
    while(1)
    {
        uart_task();
        // 其他任务...

    }
}

        3、发送数据:

                要发送一个无符号整数,调用打印函数:

                

uart_print(12345);  // 发送"12345"加换行符
uart_print(0);      // 发送"0"加换行符

UART串口处理经典程序 主要思想: 1.只要发送过来的数据就接收到buf里面 2.在while(1)里面对数据进行处理 3 从接收BUF里面取出来一个数据   如果这个数据是某个特定的值‘A’     那么我们就把它放到另一个buf1里面   然后继续取值   如果我们接收到数据‘\n’   那么我们这个buf1 表示存储结束   然后我们在处理buf1 里面的的数据。 这里面主要用到 阅读详情

相关推荐

STM32外设介绍3:(UART 和 USART 通信详解<含重定向与 DMA>)

本文详细介绍了STM32的UART/USART串口通信技术,主要内容包括: UART与USART的区别:USART支持同步/异步通信,UART仅支持异步通信 CubeMX配置方法:设置异步模式、波特率、引脚分配等 三种通信方式实现: 阻塞式发送 printf重定向方法 DMA高效传输(含发送/接收配置) 性能对比和适用场景分析 常见问题排查方法与实用建议 文章为STM32开发者提供了从基础到进阶的串口通信完整解决方案,特别强调了DMA传输和中断处理的高效实现方式。

weixin_43756295的博客 1343

串口环形缓冲区

串口环形缓冲区应用于嵌入式、物联网开发时,当串口接收数据量过大,此时MCU来不及处理而设计的一套算法,将接收的数据存入一个数组,等待空闲时再做处理。

小途的博客 3545

超详细!新手必看STM32-DMA配置与实验(串口使用DMA发送数据)

DMA就是:直接存储器访问。DMA传输数据从一个地址空间复制到另一个地址空间,提供在外设和存储器或者存储器和存储器之间的高速数据传输。

qq_1033275663的博客 2万+

串口实用的循环缓冲区

小记。 项目临时需要单片机进行节点控制,主要用来控制模块的开关,以串口进行通讯。 单片机几多久没玩了,选用的是C8051F920,传说中增强型51,不过看了Datesheet. 还是51而已。。无难度,项目要求主要是功耗的问题,5年内只能更换一次电池。 蛀牙用到模块是定时器,几个GPIO,smaRTClock,串口。 主要在通讯协议这部分花的时间较多,串口接收采用循环缓冲区的方式,以FI

流水 3758

嵌入式串口通信中循环缓冲区解决黏包拆包问题

循环缓冲区(环形队列)是一种基础且关键的嵌入式数据流管理机制,其核心原理是利用模运算实现内存空间的时空复用,通过读写索引分离生产者与消费者,天然规避数据覆盖。该结构在串口通信中具有显著技术价值:为异步、不定长、易受中断延迟影响的字节流提供稳定有序的数据暂存能力,是解决拆包(frame fragmentation)、黏包(frame sticking)等协议层解析难题的底层支撑。典型应用场景包括STM32空闲中断接收、传感器批量上报、OTA固件分片传输及多设备命令调度。本文聚焦于基于HAL库的轻量级实现与串口

weixin_42309599的博客 41

循环缓冲区解决串口黏包拆包与数据覆盖

循环缓冲区是一种经典的嵌入式内存管理机制,通过环形数组与双索引(读/写指针)实现生产者-消费者解耦。其核心原理在于以空间换时间,规避动态分配、确保O(1)操作,并借助volatile语义保障中断与主循环上下文间的数据可见性。该机制天然支撑跨中断数据拼接与帧边界识别,是应对串口通信中黏包、拆包及数据覆盖等典型问题的底层基石。在无RTOS的裸机或HAL库环境中,它为自定义协议解析提供确定性、低开销且可验证的缓冲基础,广泛应用于STM32、ESP32等主流MCU平台的工业通信、传感器交互与设备控制场景。

weixin_42309599的博客 95

STM32串口数据接收 --环形缓冲区

STM32串口数据接收 --环形缓冲区 环形缓冲区简介   在单片机中串口通信是我们使用最频繁的,使用串口通信就会用到串口的数据接收与发送,环形缓冲区方式接收数据可以更好的保证数据丢帧率第。   在通信程序中,经常使用环形缓冲器作为数据结构来存放通信中发送和接收的数据。环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对缓冲区的互斥访问。   环形缓冲区的一个有用特性是:当一个数据元素被用掉后,其余数据元素不需要移动其存储位置。相反,一个非圆形缓冲区(例如一个普通的队列)在用掉一个数据元素后,其余数据

weixin_44453694的博客 7056

COMSOL金属氢化物-放氢过程

"层流"的出口设置压降函数,解决“找不到一致的初始值”问题,主要是一开始设置出口为1atm的话,压力场过渡太剧烈,不好找到初始解,要么就先算个稳态流场,这种也能求解。注:P0是根据实测PCT的插值曲线(函数名称为:p_iso)得到的,根据初始质量储氢量wtw0,和初始温度条件T0,然后根据函数p_iso(wtw0)*exp(-deltHd/R_const*(1/T0-1/303.15[K]))求解获得。若"初始步长"选择框不勾上,前面0~5s内的求解容易发散,然后求解失败。2、设置"达西定律"的。

qq_24800941的博客 1930

linux 串口环形缓冲区,环形缓冲区的实现原理(ring buffer)(小寿转载 )

在通信程序中,经常使用环形缓冲区作为数据结构来存放通信中发送和接收的数据。环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对缓冲区的互斥访问。1、环形缓冲区的实现原理环形缓冲区通常有一个读指针和一个写指针。读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取和写入。在通常情况下,环形缓冲区的读用户仅仅会影响读指针,而写用户仅...

weixin_39610631的博客 854

【速通版!语义通信基础与前沿学习计划】

🧠语义通信基础与前沿学习计划

dally2的博客 1413

基于CubeMX与lwip的STM32轻量级HTTP服务器搭建及VSCode高效开发指南

本文详细介绍了如何在STM32单片机上,利用STM32CubeMX图形化配置工具和轻量级TCP/IP协议栈lwIP,快速搭建一个轻量级HTTP服务器。通过结合VSCode的高效代码编辑能力,提供了一套从硬件连接到动态网页交互(SSI/CGI)的完整开发指南,旨在为嵌入式设备提供零成本、跨平台的Web交互界面。

weixin_29163857的博客 585

[MSPM0开发]之七 MSPM0G3507 UART串口收发、printf重定向,循环缓冲解析自定义协议等

UART 控制器包含以下特性:• 完全可编程串行接口– 5、 6、 7 或== 8 个数据位==– 偶校验、奇校验、固定校验或无奇偶校验位生成与检测– 可产生 1 或 2 个停止位– 最低有效位或最高有效位数据最先传送和接收断线检测– 输入信号上的干扰滤波器– 可编程波特率生成, 过采样率为 16、 8 或 3 倍•独立的发送和接收 4 深度 FIFO可减少 CPU 中断服务负载• 支持DMA数据传输• 提供标准的基于 FIFO 深度的中断以及发送结束中断。

wo4fisher的博客 1万+

74hc595驱动模块的Verilog设计(线性状态机)

module hc595_driver( input clk, //50Mhz input rst_n, //复位信号 input [15:0] data, //数码管待显示数据,8位段选数据,8位位选数据 input en, //使能 o...

qq_41294540的博客 3744

linux串口驱动之三发送

本文分析了Linux TTY子系统的写入流程,重点探讨了数据从用户层到硬件驱动的传输机制。系统采用分层架构:用户层接口处理内存分配和数据拷贝;线路规程层(ldisc)负责数据加工或原始传输模式选择;通用驱动层管理4K环形缓冲区;芯片驱动层控制硬件FIFO。关键机制包括:数据分块策略(2K/64K)、并发控制(自旋锁/信号量)、缓存管理(head/tail指针操作)和进程调度(休眠/唤醒)。系统通过门限值(256字节)触发进程唤醒,确保高效数据传输,同时平衡系统资源使用和进程调度公平性。

平面到立体 1206

用Origin快速拟合荧光寿命、PL Decay (TRPL)数据分析处理

用Origin快速拟合荧光寿命、PL Decay (TRPL)数据分析处理

A20802013的博客 2万+

Ubuntu技巧-Ubuntu远程访问之SSH反向代理

💡大家好,我是可夫小子,《小白玩转ChatGPT》专栏作者,关注AIGC、互联网和自媒体。要把内网的一台的Ubuntu服务器让外面也能访问,总共有三种可行的方案,前面已经介绍了两种方式,今天就来介绍更健壮稳定的方式——ssh反向代理。大概的框架图如下,今天就从服务器购买到设置,手把手的教程,让你花费100块以内,就拥有一个强大的「云服务器」。

可夫小子的频道 1153

STM32 RS485串口DMA发送问题记录及调试解决

STM32 串口DMA接收与发送

weixin_44124535的博客 5837

【100%通过率】华为od机试C卷【出差 / 员工派遣】Java&Go 实现

某公司部门需要派遣员工去国外做项目。现在,代号为 x 的国家和代号为 y 的国家分别需要 cntx 名和 cnty 名员工部门每个员工有一个员工号 (1,2,3,......),工号连续,从 1开始。部长派遣员工的规则:

MISAYAONE的博客 2642

DSC28034PNT开发板串口驱动设计与循环缓冲区实现

串口通信作为嵌入式系统的核心基础外设,其驱动设计直接影响系统实时性与可靠性。传统轮询方式存在CPU资源浪费、响应延迟等问题,而基于循环缓冲区的中断驱动方案通过硬件FIFO与软件缓冲的协同,实现了微秒级响应与零拷贝数据传输。在TMS320F28034等DSP平台上,该方案利用UART模块的16字节硬件FIFO和可编程中断触发机制,配合环形缓冲区的无锁并发访问特性,可稳定支持115200bps及以上波特率的工业通信场景。特别在Modbus RTU、调试终端等典型应用中,双缓冲结构和动态流量控制机制能有效应对数据

weixin_30745553的博客 445

工业级Modbus ASCII实时监控系统(WinForms完整实现)

本文介绍了一个基于WinForms的工业级Modbus ASCII实时监控系统实现方案。该系统采用经典工控界面布局,包含串口配置、数据采集控制和实时数据显示三大区域。核心功能包括:串口通信参数设置、Modbus从站地址配置、寄存器数据采集、实时数据表格展示和趋势图绘制。系统通过ModbusAsciiClient类实现通信核心,采用定时器轮询机制采集数据,支持最多100个数据点的历史趋势显示。界面设计注重用户体验,配置区位于左侧,主显示区在右侧,底部为状态和日志区,符合工业控制系统的操作习惯。代码示例展示了窗

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 279

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

第31讲 循环缓冲区与命令解析

串口在持续接收数据时容易发生数据黏包(先接收的数据尚未被处理,后面的数据已经将内存覆盖)的情况,循环缓冲区的本质就是将串口接受到的数据马上拷贝到另外一块内存之中。为了避免新来的数据覆盖掉尚未处理的数据,一方面缓冲区的长度需要有一定的冗余,另外一方面需要引入写索引(写指针)始终指向未写数据区域的开头。与此同时,为了防止写入buffer的新数据把尚未处理的旧数据覆盖掉,我们还需要引入读索引的机制,让其指向正在解析的数据的开头。CPU解析完成一帧数据之后再让readIndex指向下一帧需要解析的数据。

qq_59757948的博客 717

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

4组串口UART使用DMA收发

服务器繁忙,请稍后再试

czhaii的专栏 188

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【单片机期末】串行口循环缓冲区发送

如果往串行口内发送了数据,那么会导致中断再次产生,如果没有往串行口里发送数据,则主程序中就不会再次产生中断。回环的目的是让头和尾相接,因为能实现回环,所以可以实现缓冲区不停地被重复利用,相当于是一个无穷大的缓冲区。单片机的程序可以分为两种:主程序和中断服务程序,其中主程序可以被中断服务程序打断。串行口循环缓冲区的方式非常难理解,这是一个主程序和中断服务程序相互交织的过程。如果要送出7个数字,就将UARTSave_Index从5变成7。一个字节 = 8位,单片机是10位的UART。

Dec06_Sgr_Liu的博客 904

MCU-串口发送实现

MCU-串口发送实现 例程仓库:https://gitee.com/ll0_0ll/MCU-UART 1.串口发送寄存器为空中断+RingBuff 初始化一段内存空间作循环队列 发送数据时,先将数据放到循环队列中,然后开启发送寄存器为空中断(USART_IT_TXE) 在中断中,判断队列中是否有数据,有数据就发送,没有数据就关闭中断 void uart1_send_bytes(unsigned char *data, unsigned int len) { ringbuf_write(&a

tang0_0 714

NXP EDMA学习(3):Scatter/Gather模式之串口循环缓冲区的实现

在实际应用中,循环缓冲区的使用十分广泛,如果DMA每次接收一定字节然后再在中断中写入自己定义的循环缓冲区,这样又失去了使用DMA的意义。所以硬件上的循环缓冲区的实现非常重要。大部分芯片支持DMA循环模式,而NXP的eDMA则可以通过模式来实现硬件循环缓冲区。

主要分享嵌入式软件、人工智能部分知识 1941
上一篇: STM32 关闭pwm输出,并固定高/低电平
下一篇: 单线传输三通道(RGB)驱动控制代码
dounc
博客等级 码龄6年 4粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值