上位机图像处理和嵌入式模块部署(mcu 项目1:固件编写)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        说完了上位机的开发,接下来就是固件的开发。前面我们说过,目前使用的开发板是极海apm32f103的开发板。它自身包含了iap示例,里面既有bootloader的代码,也有app的代码。所以,我们需要做的就是在app的基础之上,添加自己需要的功能就可以了,bootloader就不用处理了。这也是大部分mcu模块的开发方式。

1、修改中断向量基地址和链接地址

        这部分代码如果不修改的话,我们需要每次通过bootloader来加载app的bin文件。这对于开发来说,不是很方便,所以这部分还是建议修改一下,等到最后部署的时候再改回来。其实,修改的地方就两处,

#define FLASH_APP1_ADDR 0x0000

        还有一处就是链接的地方,

2、添加新的串口

        之前我们使用了debug串口,可以写数据、读数据。实际上开发的时候需要两个串口,最好分开来。一个串口用于debug调试,一个用于和上位机之间的通信。现在是这么安排的,之前的debug串口,也就是pa9、pa10用于串口通信使用。这里重新添加一个usart3,用于调试使用,对应的pin脚是pb10、pb11,这部分可以通过厂家的芯片手册查找到。其中,头文件的定义如下所示,

#ifndef __USART3_H
#define __USART3_H

#include "./SYSTEM/sys/sys.h"
#include "apm32f10x_usart.h"
#include <stdio.h>


#define USART3_TX_GPIO_PORT          GPIOB
#define USART3_TX_GPIO_PIN           GPIO_PIN_10
#define USART3_TX_GPIO_CLK_ENABLE()  do{ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB); }while(0)     

#define USART3_RX_GPIO_PORT          GPIOB
#define USART3_RX_GPIO_PIN           GPIO_PIN_11
#define USART3_RX_GPIO_CLK_ENABLE()  do{ RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB); }while(0)     

#define USART3_UX                    USART3
#define USART3_UX_IRQn               USART3_IRQn
#define USART3_UX_IRQHandler         USART3_IRQHandler
#define USART3_UX_CLK_ENABLE()       do{ RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_USART3); }while(0)    

void usart3_init(uint32_t baudrate);            
int sendChar(int ch);                            
void sendString(char* str);                      
void sendNumber(int num);                       

#endif

        具体的c实现代码如下所示,

#include "./SYSTEM/usart3/usart3.h"
#include "apm32f10x_rcm.h"
#include "apm32f10x_gpio.h"
#include "apm32f10x_misc.h"

void usart3_init(uint32_t baudrate)
{
    GPIO_Config_T gpio_init_struct = {0};
    USART_Config_T usart_init_struct = {0};
    
    USART3_UX_CLK_ENABLE();
    USART3_TX_GPIO_CLK_ENABLE();
    USART3_RX_GPIO_CLK_ENABLE();
    
    gpio_init_struct.pin = USART3_TX_GPIO_PIN;
    gpio_init_struct.speed = GPIO_SPEED_50MHz;
    gpio_init_struct.mode = GPIO_MODE_AF_PP;
    GPIO_Config(USART3_TX_GPIO_PORT, &gpio_init_struct);
    
    gpio_init_struct.pin = USART3_RX_GPIO_PIN;
    gpio_init_struct.speed = GPIO_SPEED_50MHz;
    gpio_init_struct.mode = GPIO_MODE_IN_PU;
    GPIO_Config(USART3_RX_GPIO_PORT, &gpio_init_struct);
    
    usart_init_struct.baudRate = baudrate;                    
    usart_init_struct.wordLength = USART_WORD_LEN_8B;         
    usart_init_struct.stopBits = USART_STOP_BIT_1;         
    usart_init_struct.parity = USART_PARITY_NONE;            
    usart_init_struct.mode = USART_MODE_TX_RX;              
    usart_init_struct.hardwareFlow = USART_HARDWARE_FLOW_NONE; 
    USART_Config(USART3_UX, &usart_init_struct);
    USART_Enable(USART3_UX);
}

int sendChar(int ch)
{
    while (USART3_UX->STS_B.TXCFLG == 0);    
	
    USART3_UX->DATA_B.DATA = (uint16_t)ch;   
    return ch;
}

void sendString(char* str)
{
		char* pStart = str;
	
		while(*pStart)
		{
			  sendChar(*pStart);
			  pStart++;
		}
}

static void _sendNumber(int num)
{
	    if(num > 9)
		{
	        sendNumber(num / 10);
		}
		
		num = num % 10;
		switch(num)
		{
			case 0:
				sendChar('0');
			    break;
			
			case 1:
				sendChar('1');
			    break;
			
			case 2:
				sendChar('2');
			  break;
			
			case 3:
				sendChar('3');
			    break;
			
			case 4:
				sendChar('4');
			    break;
			
			case 5:
				sendChar('5');
			    break;
			
			case 6:
				sendChar('6');
			    break;
			
			case 7:
				sendChar('7');
			    break;
			
			case 8:
				sendChar('8');
			    break;
			
			case 9:
				sendChar('9');
			    break;
			
			default:
				break;
		}
}

void sendNumber(int num)
{
	unsigned int val;
	if(num < 0)
	{
		sendChar('-');
        val = -num;
	}
	else
	{
		val = num;
	}
	
	_sendNumber(val);
}

        为了调试的方便,我们还实现了sendChar、sendString、sendNumber三个函数,到时候可以直接利用这几个打印函数调试即可。

3、添加内部flash读写代码

        因为涉及到参数的保存,所以势必涉及到内部flash的读写。这部分内容可以直接从对应的示例代码中copy即可,

uint16_t apmflash_read_halfword(uint32_t faddr);
void apmflash_read(uint32_t raddr, uint16_t *pbuf, uint16_t length); 
void apmflash_write_nocheck(uint32_t waddr, uint16_t *pbuf, uint16_t length);
void apmflash_write(uint32_t waddr, uint16_t *pbuf, uint32_t length);  
void test_write(uint32_t waddr, uint16_t data);                 

4、添加adc代码

        和内部flash读写一样,目前adc也有现成的case可以参考,所以相关代码直接copy即可,

void adc_init(void);
uint16_t adc_get_result(uint8_t ch); 
uint16_t adc_get_result_average(uint8_t ch, uint8_t times); 

5、确认之前的串口接收协议

        除了上面4点之外,还要确认下当前之前debug串口是否包含有接收功能,相关的逻辑是什么。通过仔细阅读代码,正好在中断处理里面发现了相关的逻辑,

void USART_UX_IRQHandler(void)
{
    if (USART_ReadIntFlag(USART_UX, USART_INT_RXBNE) == SET)
    {     
        g_rx_buffer[0] = USART_RxData(USART_UX);   
        
        if ((g_usart_rx_sta & 0x8000) == 0)      
        {
            if (g_usart_rx_sta & 0x4000)         
            {
                if (g_rx_buffer[0] != 0x0A)
                {
                    g_usart_rx_sta = 0;            
                }
                else
                {
                    g_usart_rx_sta |= 0x8000;      
                }
            }
            else                                   
            {
                if (g_rx_buffer[0] == 0x0D)
                {
                    g_usart_rx_sta |= 0x4000;
                }
                else
                {
                    g_usart_rx_buf[g_usart_rx_sta & 0x3FFF] = g_rx_buffer[0];
                    g_usart_rx_sta++;
                    if (g_usart_rx_sta > (USART_REC_LEN - 1))
                    {
                        g_usart_rx_sta = 0;       
                    }
                }
            }
        }
        
        USART_ClearIntFlag(USART_UX, USART_INT_RXBNE);
    }
}

6、gpio高低电平设定

        这部分之前的demo已经设定好,直接skip即可。

7、总结

        等我们想好要实现哪些功能的时候,其实做起来并不麻烦,关键是前面要规划好。还有一点,就是要善于复用厂家给出的demo代码,以及阅读厂家的芯片手册,这些第一手的资料不一定文档上能找到,只能自己通过文档阅读的方法一点、一点去挖掘,总是可以解决的。

        最后要提及的就是版本管理,非常推荐大家在本地用git把代码管起来。不管过分相信自己的记忆力,好记忆不如烂笔头。回到代码本身,就是好记忆不如git软件好使。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/773617.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux - Shell 以及 权限问题

目录 Shell的运行原理 Linux权限问题 Linux权限的概念 如何实现用户账号之间的切换 如何仅提升当前指令的权限 如何将普通用户添加到信任列表 Linux权限管理 文件访问者的分类&#xff08;人&#xff09; 文件类型和访问权限&#xff08;事物属性&#xff09; 文件权限值的表…

【linux高级IO(一)】理解五种IO模型

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux高级IO 1. 前言2. 重谈对…

Linux之文本三剑客

Linux之三剑客 Linux的三个命令,主要是用来处理文本,grep,sed,awk,处理日志的时候使用的非常多 1 grep 对文本的内容进行查找 1) 基础用法 语法 grep 选项 内容|正则表达式 文件选项: -i 不区分大小写 -v 排除,反选 -n 显示行号 -c 统计个数查看文件里包含有的内容 [roo…

【项目管理】项目风险管理(Word原件)

风险和机会管理就是在一个项目开发过程中对风险进行识别、跟踪、控制的手段。风险和机会管理提供了对可能出现的风险进行持续评估&#xff0c;确定重要的风险机会以及实施处理的策略的一种规范化的环境。包括识别、分析、制定处理和减缓行动、跟踪 。合理的风险和机会管理应尽力…

【TB作品】体重监控系统,ATMEGA16单片机,Proteus仿真

机电荷2018级课程设计题目及要求 题1:电子称重器设计 功能要求: 1)开机显示时间(小时、分)、时分可修改; 2)用滑动变阻器模拟称重传感器(测量范围0- 200g),数码管显示当前重量值,当重量值高于高 值时,红灯长亮; 3)当重量值低于低值时,黄灯长亮; 4)当重量值在正常值时,绿灯亮; 5…

Exploting an API endpoiint using documentation

HTTP request methods https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods 第一步:burp抓包刷新页面 httphistory中只能看到两个记录,可以看下Response,是HTML页面,说明这里有HTML页面 ,但是没有发现特定的API接口。 第二步:用户登录 转到用户登录的功能点处…

Android --- Service

出自于此&#xff0c;写得很清楚。关于Android Service真正的完全详解&#xff0c;你需要知道的一切_android service-CSDN博客 出自【zejian的博客】 什么是Service? Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件。 服务可由其他应用组件…

【Python】已解决:ValueError: Worksheet named ‘Sheet’ not found

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ValueError: Worksheet named ‘Sheet’ not found 一、分析问题背景 在Python编程中&#xff0c;处理Excel文件是一个常见的任务。通常&#xff0c;我们会使用…

DFS之搜索顺序——AcWing 1116. 马走日

DFS之搜索顺序 定义 DFS之搜索顺序是指在执行深度优先搜索时&#xff0c;遍历图或树中节点的策略。具体而言&#xff0c;DFS会沿着一条路径深入到底&#xff0c;当无法继续深入时回溯&#xff0c;然后选择另一条未探索的路径继续深入。搜索顺序直接影响到搜索效率和剪枝的可能…

线性代数|机器学习-P21概率定义和Markov不等式

文章目录 1. 样本期望和方差1.1 样本期望 E ( X ) \mathrm{E}(X) E(X)1.2 样本期望 D ( X ) \mathrm{D}(X) D(X) 2. Markov 不等式&Chebyshev不等式2.1 Markov不等式公式 概述2.2 Markov不等式公式 证明&#xff1a;2.3 Markov不等式公式 举例&#xff1a;2.4 Chebyshev不…

HarmonyOS - 通过.p7b文件获取fingerprint

1、查询工程所对应的 .p7b 文件 通常新工程运行按照需要通过 DevEco Studio 的 Project Structure 勾选 Automatically generate signature 自动生成签名文件&#xff0c;自动生成的 .p7b 文件通常默认在系统用户目录下. 如&#xff1a;C:/Users/zhangsan/.ohos/config/default…

QT学习(6)——QT中的定时器事件,两种实现方式;事件的分发event,事件过滤器

目录 引出定时器事件QTimerEventQTimer 事件的分发事件过滤器 总结QT中的鼠标事件定义QLable的鼠标进入离开事件提升为myLabel重写QLabel的函数鼠标的事件鼠标的左中右键枚举鼠标多事件获取和鼠标移动鼠标追踪 QT中的信号和槽自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.…

了解 PostgerSQL 的门户 – Executor vs Process Utility

当您向 PostgreSQL 发送查询时&#xff0c;查询会依次经历多个处理阶段&#xff0c;并在最后返回结果。这些阶段称为&#xff1a; 解析 分析 重写 计划 执行 在另一篇文章中&#xff0c;我简要概述了PostgreSQL在每个查询处理阶段的主要责任。你可以在这里找到它。 https…

SS8812T替代DRV8812的国产双通道H桥电机驱动芯片

由工采网代理的SS8812T是一款国产双通道H桥电机驱动芯片&#xff1b;该芯片为打印机和其它电机一体化应用提供一种双通道集成电机驱动方案&#xff1b;可Pin-to-Pin兼容替代DRV8812&#xff0c;可广泛应用于POS、打印机、安防相机、办公自动化设备、游戏机、机器人等。 产品描述…

14-8 小型语言模型的兴起

过去几年&#xff0c;我们看到人工智能能力呈爆炸式增长&#xff0c;其中很大一部分是由大型语言模型 (LLM) 的进步推动的。GPT-3 等模型包含 1750 亿个参数&#xff0c;已经展示了生成类似人类的文本、回答问题、总结文档等能力。然而&#xff0c;虽然 LLM 的能力令人印象深刻…

第14届蓝桥杯Python青少组中/高级组选拔赛(STEMA)2022年8月21日真题

第14届蓝桥杯Python青少组中/高级组选拔赛&#xff08;STEMA&#xff09;2022年8月21日真题 题目总数&#xff1a;5 总分数&#xff1a;128 更多真题下载点我&#x1f447;https://pan.baidu.com/s/1JRLLwW2C-OBbcY2tJ3uYJg?pwd2wk2 编程题 第 1 题 问答题 编程实现&…

antd实现简易相册,zdppy+vue3+antd实现前后端分离相册

前端代码 <template><a-image:preview"{ visible: false }":width"200"src"http://localhost:8889/download/1.jpg"click"visible true"/><div style"display: none"><a-image-preview-group:previe…

【设计模式】设计模式学习线路与总结

文章目录 一. 设计原则与思想二. 设计模式与范式三. 设计模式进阶四. 项目实战 设计模式主要是为了改善代码质量&#xff0c;对代码的重用、解耦以及重构给了最佳实践&#xff0c;如下图是我们在掌握设计模式过程中需要掌握和思考的内容概览。 一. 设计原则与思想 面向对象编…

PMP--知识卡片--波士顿矩阵

文章目录 记忆黑话概念作用图示 记忆 一说到波士顿就联想到波士顿龙虾&#xff0c;所以波士顿矩阵跟动物有关&#xff0c;狗&#xff0c;牛。 黑话 你公司的现金牛业务&#xff0c;正在逐渐变成瘦狗&#xff0c;应尽快采取收割策略&#xff1b;问题业务的储备太少&#xff0…

AGI|Transformer自注意力机制超全扫盲攻略,建议收藏!

一、前言 2017年&#xff0c;谷歌团队推出一篇神经网络的论文&#xff0c;首次提出将“自注意力”机制引入深度学习中&#xff0c;这一机制可以根据输入数据各部分重要性的不同而分配不同的权重。当ChatGPT震惊世人时&#xff0c;Transformer也随之进入大众视野。一夜之间&…