您的位置:首页 > 汽车 > 新车 > 上位机图像处理和嵌入式模块部署(mcu 项目1:固件编写)

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

2024/7/3 22:27:31 来源:https://blog.csdn.net/feixiaoxing/article/details/140092285  浏览:    关键词:上位机图像处理和嵌入式模块部署(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软件好使。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com