- 2025-03-11
-
回复了主题帖:
《Python编程:从入门到实践》+ 巧用帮助功能来学习
okhxyyo 发表于 2025-3-11 08:57
这可真是个好主意~~谢谢分享
感谢您的支持!!!
-
回复了主题帖:
《Python编程:从入门到实践》+ 巧用帮助功能来学习
hellokitty_bean 发表于 2025-3-11 09:00
感谢分享呀。。。。。。。
不过,Turtle用处不大吧。。。。
这个看你怎样理解和使用的目标,从学习和应用方向看它又特色又完成不逊色于常规的python,那又何谈用途不大呢?
-
回复了主题帖:
《Python编程:从入门到实践》+ Python的简单测试
本帖最后由 Lily李 于 2025-3-11 08:43 编辑
Jacktang 发表于 2025-3-11 07:52 再简单,也是测试,测试成功
尽管测试已简单到无法无法再简单,的确是2种不同的方式和方向,万丈高楼平地起嘛。
- 2025-03-10
-
发表了主题帖:
《Python编程:从入门到实践》+ 开发板的Python编程
除了在window之类的系统上运用Python进行程序设计,在一些开发板上也移植了轻量级的micropython。
例如在 STM32MP135F-DK、K230嵌入式AI开发板及一些派系列的开发板都有Python的身影。
以 STM32MP135F-DK为例,它使用简捷的程序就可完成图1所示界面的制作,其程序如图2所示,它通过在指定位置显示界面效果的图片就实现漂亮的显示效果,它是既简单又高效。
图1 界面效果
图2 界面生成程序
此外,在该开发板上通过指令“apt-get install python3-gpiod”可安装GPIO资源包来获取GPIO资源。在安装成功后,使用VI编辑器就可建立名为led.py的测试文件,其内容如图3所示。
图3 程序内容
经程序运行,就可扩展LED指示灯。
图4 执行程序
由此可见,在开发板上除了编程进行计算处理,还具备了硬件资源的控制能力。
再比如在一些AI识别的开发板上,也嵌入了Python,这主要是由于许多的AI识别功能是建立在PyTorch所构建的识别模型上,而PyTorch又是基于Python,所以它们嵌有Python就不足为奇了。
K230嵌入式AI开发板为例,它基于较好的视觉识别能力,而其视觉识别模型是可以从PyTorch的数字图像处理功能移植的。
除了AI识别除了外,它也提供GPIO资源的使用,其实现LED闪烁效果的程序为:
from machine import Pin #导入Pin模块
from machine import FPIOA
import time
#将GPIO52配置为普通GPIO
fpioa = FPIOA()
fpioa.set_function(52,FPIOA.GPIO52)
LED=Pin(52,Pin.OUT) #构建led对象,GPIO52,输出
LED.value(1) #点亮LED,也可以使用led.on()
while True:
LED.value(1)
time.sleep_ms(500)
LED.value(0)
time.sleep_ms(500)
有了GPIO资源的支持,就可以幻化出各种外设功能的扩展,从而大大地增强其应用性。
-
发表了主题帖:
《Python编程:从入门到实践》+ 巧用帮助功能来学习
在Python编程软件中,配备帮助功能,借助它不但可以获得相应的帮助,也可以通过它来进行学习。
在选取IDLE运行后,按图1所示在帮助菜单下选取Turtle Demo选项。
图1 选取帮助
在弹出图2的界面后,选取Examples菜单,即可见到相应的例程选项。
图2 选取例程
以paint程序为例,在选取后其界面如图3所示。其界面的左侧是测试的程序,其右侧是运行效果的形式窗口。
图3 界面形式
在点击START键后,即开始运行程序,其效果如图4所示,即绘制出一个红点。
图4 运行程序
例程的内容如下:
from turtle import *
def switchupdown(x=0, y=0):
if pen()["pendown"]:
end_fill()
up()
else:
down()
begin_fill()
def changecolor(x=0, y=0):
global colors
colors = colors[1:]+colors[:1]
color(colors[0])
def main():
global colors
shape("circle")
resizemode("user")
shapesize(.5)
width(3)
colors=["red", "green", "blue", "yellow"]
color(colors[0])
switchupdown()
onscreenclick(goto,1)
onscreenclick(changecolor,2)
onscreenclick(switchupdown,3)
return "EVENTLOOP"
if __name__ == "__main__":
msg = main()
print(msg)
mainloop()
该程序的功能是通过主程序的循环运行,来调用2个辅助函数来绘制指定色彩的红色圆点,并在点击的情况下,快速将圆点移动到指定位置。
在点击指定位置后,其效果如图所示。
图5 调整位置
在点击STOP键后,会立即退出程序的运行,见图6所示。
图6 停止运行
此外,在例程中还有时钟计时改变指针位置的效果,见图7所示。
如此,我们借助帮助功能即可快速学习和掌握到面向对象的程序设计方法!
图7 时钟效果测试
-
发表了主题帖:
《Python编程:从入门到实践》+ 学习micropython移植(二)
接着前面的介绍,继续后续的内容。
在指定开发板的内核下运行Python,需要依赖标准库的支持,所需的标准库如下:
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdarg.h>
#include <math.h>
#include <limits.h>
#include <unistd.h> // 在py_port自己实现
注: 如果没有#include <errno.h>,则配置MICROPY_USE_INTERNAL_ERRNO为1。
#include <alloca.h> 这个编译器支持产生genhdr,可从其他已经构建的或者使用windows的样例来构建,然后复制对应的头文件。
moduledefs.h 定义了一些模块信息,由于没有使用官方的构建过程,可能没有自动更新,可以手动修改,来删减一些模块。
mpversion.h
qstrdefs.generated.h
root_pointers.h
其生成过程参考ports\windows\msvc\genhdr.targets
中的命令
<Exec Command="type $(QstrDefsCollected) >> $(DestDir)qstrdefs.preprocessed.h"/>
<Exec Command="$(PyPython) $(PySrcDir)makeqstrdata.py $(DestDir)qstrdefs.preprocessed.h > $(TmpFile)"/>
其中指定文件qstrdefscollected.h
<QstrDefsCollected>$(DestDir)qstrdefscollected.h</QstrDefsCollected>
该文件由以下命令产生
<Exec Command="$(PyPython) $(PySrcDir)makeqstrdefs.py split qstr $(DestDir)qstr.i.last $(DestDir)qstr _"/>
<Exec Command="$(PyPython) $(PySrcDir)makeqstrdefs.py cat qstr _ $(DestDir)qstr $(QstrDefsCollected)"/>
对应如下命令
makeqstrdata.py位于py目录下,在此打开cmd行,先执行
python makeqstrdefs.py split qstr qstr.i.last qstr _
python makeqstrdefs.py cat qstr _ qstr qstrdefscollected.h
再执行
type qstrdefscollected.h >> qstrdefs.preprocessed.h
再执行
python makeqstrdata.py qstrdefs.preprocessed.h > qstrdefs.generated.h.tmp
对于适配串口,需在py_port\uart_core.c中删掉#include <unistd.h>添加自己的串行接口include “uart.h”
并删掉
#if MICROPY_MIN_USE_STM32_MCU
#end
#if MICROPY_MIN_USE_STDOUT
#elif MICROPY_MIN_USE_STM32_MCU
#endif
的内容,以实现阻塞读一个字符mp_hal_stdin_rx_chr
阻塞发送字符串的接口
mp_hal_stdout_tx_strn
mp_hal_stdout_tx_strn_cooked
mp_hal_stdout_tx_str
其Uart.c的内容为:
#include <stdio.h>
#include <stdbool.h>
#include "uart.h"
#include "fifo.h"
#include <stdio.h>
#include "fr30xx.h"
#define CriticalAlloc()
#define EnterCritical() __disable_irq()
#define ExitCritical() __enable_irq()
static uint8_t s_uart_rx_buffer[64];
static fifo_st s_uart_fifo_dev=
{
.in = 0,
.len = 0,
.out = 0,
.buffer = s_uart_rx_buffer,
.buffer_len = sizeof(s_uart_rx_buffer),
};
volatile bool g_data_transmit_flag = false;
uint8_t rx_buffer[1];
void uart_rx_cb(uint8_t* buff, uint32_t len)
{
fifo_in(&s_uart_fifo_dev, buff, len);
}
uint32_t uart_send(uint8_t* buffer, uint32_t len)
{
g_data_transmit_flag = false;
for(uint32_t i=0;i<len;i++)
{
putchar(buffer);
}
return len;
}
uint32_t uart_read(uint8_t* buffer, uint32_t len)
{
uint32_t rlen;
CriticalAlloc();
EnterCritical();
rlen = fifo_out(&s_uart_fifo_dev, buffer, len);
ExitCritical();
return rlen;
}
其Uart.h的内容为:
#ifndef UART_H
#define UART_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
uint32_t uart_send(uint8_t* buffer, uint32_t len);
uint32_t uart_read(uint8_t* buffer, uint32_t len);
void uart_rx_cb(uint8_t* buff, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif
其Fifo.c的内容为:
#include <string.h>
#include "fifo.h"
#define FIFO_PARAM_CHECK 0
uint32_t fifo_in(fifo_st* dev, uint8_t* buffer, uint32_t len)
{
uint32_t space = 0;
#if FIFO_PARAM_CHECK
if((dev == 0) || (buffer == 0) || (len == 0))
{
return 0;
}
if(dev->buffer == 0)
{
return 0;
}
#endif
if(len > dev->buffer_len)
{
len = dev->buffer_len;
}
if(dev->buffer_len >= dev->len)
{
space = dev->buffer_len - dev->len;
}
else
{
dev->len = 0;
space = dev->buffer_len;
}
len = (len >= space) ? space : len;
if(len == 0)
{
return 0;
}
space = dev->buffer_len - dev->in;
if(space >= len)
{
memcpy(dev->buffer+dev->in,buffer,len);
}
else
{
memcpy(dev->buffer+dev->in,buffer,space);
memcpy(dev->buffer,buffer+space,len-space);
}
dev->in += len;
if(dev->in >= dev->buffer_len)
{
dev->in -= dev->buffer_len;
}
dev->len += len;
return len;
}
uint32_t fifo_out(fifo_st* dev, uint8_t* buffer, uint32_t len)
{
uint32_t space = 0;
#if FIFO_PARAM_CHECK
if((dev == 0) || (buffer == 0) || (len == 0))
{
return 0;
}
if(dev->buffer == 0)
{
return 0;
}
#endif
if(dev->len == 0)
{
return 0;
}
len = (dev->len) > len ? len : dev->len;
space = dev->buffer_len - dev->out;
if(space >= len)
{
memcpy(buffer,dev->buffer+dev->out,len);
}
else
{
memcpy(buffer,dev->buffer+dev->out,space);
memcpy(buffer+space,dev->buffer,len-space);
}
dev->out += len;
if(dev->out >= dev->buffer_len)
{
dev->out -= dev->buffer_len;
}
dev->len -= len;
return len;
}
uint32_t fifo_getlen(fifo_st* dev)
{
#if FIFO_PARAM_CHECK
if(dev == 0)
{
return 0;
}
#endif
return dev->len;
}
void fifo_clean(fifo_st* dev)
{
#if FIFO_PARAM_CHECK
if(dev == 0)
{
return 0;
}
#endif
dev->len = 0;
dev->in = 0;
dev->out = 0;
}
其Fifo,h的内容为:
#ifndef FIFO_H
#define FIFO_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
typedef struct
{
uint32_t in;
uint32_t out;
uint32_t len;
uint32_t buffer_len;
uint8_t* buffer;
} fifo_st;
uint32_t fifo_in(fifo_st* dev, uint8_t* buffer, uint32_t len);
uint32_t fifo_out(fifo_st* dev, uint8_t* buffer, uint32_t len);
uint32_t fifo_getlen(fifo_st* dev);
void fifo_clean(fifo_st* dev);
#ifdef __cplusplus
}
#endif
#endif
最终uart_core.c的内容为:
#include <string.h>
#include "py/mpconfig.h"
#include "uart.h"
int mp_hal_stdin_rx_chr(void) {
unsigned char c = 0;
while(0 == uart_read(&c,1))
{
};
return c;
}
mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
mp_uint_t ret = len;
uart_send((uint8_t*)str,len);
return ret;
}
void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len){
uart_send((uint8_t*)str,len);
}
void mp_hal_stdout_tx_str(const char *str){
uart_send((uint8_t*)str,strlen(str));
}
关于Py_main入口,在py_main.c中:
MICROPY_ENABLE_GC配置为0
MICROPY_ENABLE_COMPILER配置为1
MICROPY_REPL_EVENT_DRIVEN 配置为0
其执行过程为:
mp_init();->pyexec_friendly_repl();
int py_main(int argc, char **argv) {
int stack_dummy;
stack_top = (char *)&stack_dummy;
#if MICROPY_ENABLE_GC
gc_init(heap, heap + sizeof(heap));
#endif
mp_init();
#if MICROPY_ENABLE_COMPILER
#if MICROPY_REPL_EVENT_DRIVEN
pyexec_event_repl_init();
for (;;) {
int c = mp_hal_stdin_rx_chr();
if (pyexec_event_repl_process_char(c)) {
break;
}
}
#else
pyexec_friendly_repl();
#endif
#else
pyexec_frozen_module("frozentest.py", false);
#endif
mp_deinit();
return 0;
}
在完成上述的工作后,通过创建一个线程来运行py_main函数即可进行测试。
至此,就是一个从0开始移植micropython源码到自己开发板内核的过程,一通百通通过其移植的探索,为我们展现了一个最简的micropython移植过程及需要哪些文件和基本的架构。由此可见其移植工作还是比较复杂,但也为我们探索出了一条可行的道路,其借鉴意义还是十分重要的。
-
发表了主题帖:
《Python编程:从入门到实践》+ Python的简单测试
我使用的Python版本是V3.10,安装后它在开始菜单下其功能选项如图1所示。
图1 Python功能项
Python程序的运行方式有两种,即交互式和文件式。
所谓交互式是指Python解释器是以逐行接收Python代码的形式来即时响应处理,而文件式也被称为批量式,是指它先将Python代码保存到文件中,再启动Python解释器以批量的方式解释处理。
对于交互式运行,是在开始菜单下选取Python 3.10(64-bit)选项,其界面如图2所示。
此时,直接输入赋值指令和打印指令即可看到计算结果。
图2 运行界面及测试结果
此外,Python解释器还捆绑了Python的官方开发工具----IDLE,它集成了开发与学习环境。
在开始菜单下选取IDLE(Python 3.1064-bit)选项,即可启用IDLE,其界面如图3所示。
图3 使用界面
在IDLE环境下,其测试的过程如图4所示。
图4 使用界面
对于文件式处理,它要创建Python文件,其文件的后缀为*.py。
使用文件菜单下的新建文件选项,可打开文件编辑器,见图5所示。
图5 新建文件
然后按图6所示,输入测试语句并命名为hollow.py加以保存。
图6 编写程序
随后,按图7所示即可以文件式运行该程序文件,其执行结果如图8所示。
图7 运行程序
图8 运行结果
-
发表了主题帖:
《Python编程:从入门到实践》+ 学习micropython移植(一)
在阅读《Python 编程从入门到实践》这本书之余,还了解了一些其它的Python知识。
最近,关注了一个有指定命题的有奖测评活动,其中一个命题就是将micropython移植到指定的开发板上并实现音乐播放功能。这期间就见识到一位大神,单枪匹马地一骑绝尘,快速实现了设计目标。这其中最核心的一项工作就是将Python移植到开发板上。
在通常情况下,我们使用Python是在电脑上以软件的方式。再一种情况就是在相应的开发板上,使用厂家已经移植好的MicroPython。
至于如何将MicroPython移植到特点的开发板上,确实有着一层神秘的面纱。
MicroPython 是 Python 3 的一种精简而高效的实现,它包含了一部分经过优化的Python 标准库,能在微控制器资源有限的情况下运行。至于MicroPython,也支持一些高级功能,比如交互式提示、任意精度的整数、列表推导、生成器、异常处理等。
其实现的体量极小,可以在只有 256K的代码空间和 16K 的内存空间上运行。它特别适于移植到MCU上使用。
MicroPython 的设计也是尽量和普通的 Python 兼容,这样能轻松地把代码从桌面平台搬到微控制器或者嵌入式系统上运行。
在搭建好micropython环境的情况下,可以直接编写python脚本进行相应的验证和测试,从而有利于工作效率的提高。
那么关键的问题来了,该如何进行python的定向移植呢?
这主要是依赖官方所提供的各种pyboard的适配,可以直接编译成对应的固件来使用。而对于特定的开发板,官方是没有提供适配的,且其构建环境也不一定是用户需要的,所以一个根本性的解决方式就是使用其源码将其移植到所迁移的开发板上。
将Micropython以MDK为载体移植到CORTEX-M33平台的方法是:
先了解其代码框架,可以在官方支持的平台上完成构建,以掌握其构建过程,这样就可以获知要编译哪些源码及相应的过程。
例如可以在windows环境下,以VS打开micropython\mpy-cross\mpy-cross.vcxproj编译器。
然后再打开micropython\ports\windows\micropython.vcxproj编译解释器,以了解其工程架构。注意:在构建前需要取消所有文件的只读属性。
随后,是移植一个最小实现,即暂时不添加任何的外部模块,仅使用其内建的一些模块,整个代码框架如下:
其中,py目录下是micropyth解释器的核心代码,可以复制到自己的工程目录中。具体方法是复制其下的所有c文件到自己的工程中,并将py路径添加到头文件包含的路径。
其中以下文件是依照开发板的内核来选择,这里选取的是ARM CORTEX-M系列的smthumb.c,至于其他则不需要。
asmarm.c
asmrv32.c
asmthumb.c
asmx64.c
asmx86.c
asmxtensa.c
对于shared源码,则是添加以下内容:
Shared/runtime/pyexec.c pyexec.h
Shared/readline/readline.c readline.h
对于extmod源码,是添加以下内容:
modplatform.h,
virtpin.h
对于py_port源码,是新建一个移植文件夹py_port,可参考micropython\ports\minimal移植,将micropython\ports\minimal下的文件复制到py_port路径下,并将py_port添加到自己的工程目录中。
具体文件为:uart_core.c实现串口输入输出接口,mpconfigport.h是配置文件,mphalport.h是一些hal层接口实现,py_main是解释器入口,qstrdefsport.h
unistd.h是类似unix平台的替代。
对于Py_main.c,是将py_port/main.c改为py_port/py_main.c
默认是基于stm32或者pc主机的实现,此处需要按照自己的开发板内核做一定的修改。
将一下的内容都注释掉,以使用自己开发板内核。
#if MICROPY_MIN_USE_STM32_MCU
#endif
#if MICROPY_MIN_USE_CORTEX_CPU
#endif
将main函数名改为py_main,以实现在自己开发板下的调用。
在确保能通过编译下,再解决py_main的实现。
对于Uart_core.c,需要实现以下接口:
#include "py/mpconfig.h"
int mp_hal_stdin_rx_chr(void) {
unsigned char c = 0;
return c;
}
mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
mp_uint_t ret = len;
return ret;
}
void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len){
}
void mp_hal_stdout_tx_str(const char *str){
}
对于Unistd.h,需定义ssize_t及其一些宏:
#ifndef MICROPY_INCLUDED_UNISTD_H
#define MICROPY_INCLUDED_UNISTD_H
typedef int ssize_t;
#define F_OK 0
#define W_OK 2
#define R_OK 4
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
#endif
对于mphalport.h,其内容为:
Hal层接口
static inline mp_uint_t mp_hal_ticks_ms(void) {
return 0;
}
static inline void mp_hal_set_interrupt_char(char c) {
}
对于mpconfigport.h配置文件,其中需要关注的是MICROPY_PY_XXX的宏配置是否使能某些模块。
#include <stdint.h>
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_MINIMUM)
#define MICROPY_ENABLE_COMPILER (1)
#define MICROPY_HELPER_REPL (1)
#define MICROPY_MODULE_FROZEN_MPY (0)
#define MICROPY_ENABLE_EXTERNAL_IMPORT (0)
#define MICROPY_PY_IO (0)
#define MICROPY_PY_IO_IOBASE (1)
#define MICROPY_PY_ERRNO (1)
#define MICROPY_PY_MATH (1)
#define MICROPY_PY_CMATH (1)
#define MICROPY_PY_BUILTINS_FLOAT (1)
#define MICROPY_PY_BUILTINS_COMPLEX (1)
#define MICROPY_PY_GC (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_PY_SYS (1)
#define MICROPY_PY_MICROPYTHON (1)
#define MICROPY_USE_INTERNAL_PRINTF (0)
#define MICROPY_PY_ARRAY (1)
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
#define MICROPY_ALLOC_PATH_MAX (256)
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16)
typedef intptr_t mp_int_t;
typedef uintptr_t mp_uint_t;
typedef long mp_off_t;
#include <alloca.h>
#define MICROPY_HW_BOARD_NAME "minimal"
#define MICROPY_HW_MCU_NAME "unknown-cpu"
#define MICROPY_HEAP_SIZE (2048)
#define MP_STATE_PORT MP_STATE_VM
#define MICROPY_USE_INTERNAL_ERRNO 1
由于内容很多,先暂时分享到这里,后续在接着介绍。
- 2025-03-01
-
回复了主题帖:
【N32A455 车规MCU开发板测评】TF卡读写与检测数据记录
wangerxian 发表于 2025-2-28 19:56
可以测试一下写TF文件的速率能达到多少。
有时间去测测
- 2025-02-24
-
发表了主题帖:
【N32A455 车规MCU开发板测评】TF卡读写与检测数据记录
N32A455开发板上配有TF卡读写接口,见图1所示,在为其添加TF卡读写的文件管理功能后,可实现检测数据的文件记录功能。
图1 TF卡接口
这里就将A/D数据采集中的内部温度检测功能迁移到TF卡文件存储中,以实现检测温度的记录。
实现检测温度文件保存的函数为:
void File_record(void)
{
FATFS FatFs;
FIL File;
UINT br = 0, bw = 0;
FRESULT Result;
uint8_t i;
uint8_t Buffer[200];
memset(Buffer, 0, sizeof(Buffer));
Result = f_mount(&FatFs, "0:", 1);
Result = f_open(&File, "TEST.TXT", FA_CREATE_ALWAYS | FA_WRITE);
while(GPIO_ReadInputDataBit(GPIOD,GPIO_PIN_12)== )
{
TempValue = TempCal(ADCConvertedValue);
sprintf(Buffer, "Temperature = %.3f C\r\n", TempValue);
f_write(&File, Buffer, 30, &bw);
Delay(500);
}
if (Result != RES_OK)
{
printf("\r\nf_write TEST.txt Fail! Result = %d\r\n", Result);
}
else
{
printf("\r\nf_write TEST.txt Result = %d, bw = %d\r\n", Result, bw);
f_sync(&File);
}
f_close(&File);
}
实现片内温度检测及文件记录的主程序为:
int main(void)
{
uint32_t testResult = 0;
RCC_Configuration();
DMA_DeInit(DMA1_CH1);
DMA_InitStructure.PeriphAddr = (uint32_t)&ADC1->DAT;
DMA_InitStructure.MemAddr = (uint32_t)&ADCConvertedValue;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = 1;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_DISABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR;
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(DMA1_CH1, &DMA_InitStructure);
DMA_EnableChannel(DMA1_CH1, ENABLE);
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = DISABLE;
ADC_InitStructure.ContinueConvEn = ENABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_EnableTempSensorVrefint(ENABLE);
ADC_InitStructureEx.VbatMinitEn = ENABLE;
ADC_InitStructureEx.DeepPowerModEn = DISABLE;
ADC_InitStructureEx.JendcIntEn = DISABLE;
ADC_InitStructureEx.EndcIntEn = DISABLE;
ADC_InitStructureEx.ClkMode = ADC_CTRL3_CKMOD_AHB;
ADC_InitStructureEx.CalAtuoLoadEn = DISABLE;
ADC_InitStructureEx.DifModCal = false;
ADC_InitStructureEx.ResBit = ADC_CTRL3_RES_12BIT;
ADC_InitStructureEx.SampSecondStyle = false;
ADC_InitEx(ADC1, &ADC_InitStructureEx);
ADC_ConfigRegularChannel(ADC1, ADC_CH_16, 1, ADC_SAMP_TIME_239CYCLES5);
ADC_EnableTempSensorVrefint(ENABLE);
ADC_EnableDMA(ADC1, ENABLE);
ADC_Enable(ADC1, ENABLE);
while(ADC_GetFlagStatusNew(ADC1,ADC_FLAG_RDY) == RESET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));
ADC_EnableSoftwareStartConv(ADC1, ENABLE);
USART1_Config();
key_Config();
V30 = *(__IO uint32_t*)((uint32_t)0x1FFFF7D0);
log_init();
Memset(Buf_RX, 0x00, Buf_Len);
Fill_Buffer(Buf_TX, Buf_Len, 0x00);
Status = SD_Init(0, 3, 4);
File_record();
while (1);
}
经程序的编译与下载,其测试结果如图2和图3所示。
图2 串口输出内容
图3 文件记录内容
- 2025-02-21
-
发表了主题帖:
《Python编程:从入门到实践》+ 初体验
《Python 编程从入门到实践》这本书由美国的埃里克.马瑟斯编著,他致力于推动Python编程在全球的普及,目前这本书是它的第三版。
该书是一本为入门的学习者而打造的读物,它由两个部分组成,即基础知识和项 目,共计20章。
该书为使读者了解Python语言的特点,它毫无疑问地达成了这个目的。
该书在代码的排版格式方面,有非常好的视觉效果,尤其是对重点代码进行了加粗加黑的处理,使读者能快速抓住知识的重点,因此对于新手来说是蛮友好的。
它在内容方面,重点介绍了Python的基础知识,包括环境的搭建、语法的介绍、数据结构等内容。在打下牢固的基础知识之余,还为读者提供了一些实战的案例,以帮助读者来巩固所学到的知识。在实践过程中,它进一步加深了学习者对Python这门编程语言的理解,并指明了应用的方向。
当然,书中也留有一些值得期待的部分,例如对于第一次学习编程的读者,可能还缺乏在编程方法方法方面的系统性问题。
另外,书中应该介绍一些如何将复杂问题分解为简单问题的处理方法。此外,在程序结构设计即程序调试方面,可以增加一些笔墨,以对应试教育者有所助力。
它在项目部分,为了进一步激发读者兴趣,在掌握Python知识的基础上,进行了一些实践。如对数据可视化方面的介绍,但书中只介绍了如何将数据转化为曲线图,却没有进一步介绍与数据可视化相关的pandas,numpy等基于python的数据分析软件包的知识,此外在进行web编程时,会涉及到mysql等数据库的知识,在这方面该书也未涉及。
对于一本从入门到实践的书来讲,它的使命就是使学习者通过学习来了解和掌握Python知识,该书还起到了这样的作用。
- 2025-02-17
-
发表了主题帖:
【N32A455 车规MCU开发板测评】I2S 音频录放功能测试
在N32A455开发板上配有CODEC芯片VS1053B,可通过接口J19输入LINE_IN信号,或以驻极体MIC来采集录音信号;还可通过输出接口J21,连接一路耳机进行播放,或通过功放芯片HT6872来驱动一路外置喇叭接口。
CODEC支持以SPI或I2S方式进行通讯,若选用SPI通讯,则需连接跳线J46、J47;若选用I2S通讯,则需连接跳线J37、J38。
详细的工作电路如图1所示:
图1 I2S 电路
进行I2S通讯测试的引脚配置函数为:
void GPIO_Configuration(void)
{
GPIO_InitType GPIO_InitStructure;
/* Disable the JTAG interface and enable the SWJ interface
This operation is not necessary for Connectivity Line devices since
SPI3 I/Os can be remapped on other GPIO pins */
GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE);
/* Configure SPI2 pins: CK, WS and SD ---------------------------------*/
GPIO_InitStructure.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
/* Configure SPI3 pins: CK and SD ------------------------------------*/
GPIO_InitStructure.Pin = GPIO_PIN_3 | GPIO_PIN_5;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
/* Configure SPI3 pins: WS -------------------------------------------*/
GPIO_InitStructure.Pin = GPIO_PIN_15;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}
因此可知,SPI2所使用的引脚为PB12、PB13、PB15,SPI3所使用的引脚为PA15、PB3、PB5。
其连接关系为:
SPI2: CK--PB12
WS--PB13
SDI--PB15
SPI3: WS--PA15
CK--PB3
SD--PB5
图2 连接关系
图3 线路连接
判别数据传送的函数为:
TestStatus Buffercmp(uint16_t* pBuffer1, uint16_t* pBuffer2, uint16_t BufferLength)
{
while (BufferLength--)
{
if (*pBuffer1 != *pBuffer2)
{
return FAILED;
}
pBuffer1++;
pBuffer2++;
}
return PASSED;
}
为便于测试观察,在测试主程序中添加了相应串口提示,主程序的内容如下:
int main(void)
{
uint16_t i;
RCC_Configuration();
GPIO_Configuration();
USART1_Config();
printf("\r\n I2S test:\r\n");
printf("\r\n I2S_MASTER_Buffer_Tx\r\n");
for(i = 0; i < 32; i++)
{
if(i % 8 == 0)
{
printf("\r\n:");
}
printf(" 0x%02X", I2S_MASTER_Buffer_Tx[i]);
}
SPI_I2S_DeInit(I2S_SLAVE);
SPI_I2S_DeInit(I2S_MASTER);
DMA_DeInit(I2S_SLAVE_Rx_DMA_Channel);
DMA_InitStructure.PeriphAddr = (uint32_t)I2S_SLAVE_DR_Base;
DMA_InitStructure.MemAddr = (uint32_t)I2S_SLAVE_Buffer_Rx;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = BufferSize;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;
DMA_InitStructure.Priority = DMA_PRIORITY_VERY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(I2S_SLAVE_Rx_DMA_Channel, &DMA_InitStructure);
DMA_DeInit(I2S_MASTER_Tx_DMA_Channel);
DMA_InitStructure.PeriphAddr = (uint32_t)I2S_MASTER_DR_Base;
DMA_InitStructure.MemAddr = (uint32_t)I2S_MASTER_Buffer_Tx;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_DST;
DMA_Init(I2S_MASTER_Tx_DMA_Channel, &DMA_InitStructure);
I2S_InitStructure.Standard = I2S_STD_PHILLIPS;
I2S_InitStructure.DataFormat = I2S_DATA_FMT_16BITS_EXTENDED;
I2S_InitStructure.MCLKEnable = I2S_MCLK_DISABLE;
I2S_InitStructure.AudioFrequency = I2S_AUDIO_FREQ_48K;
I2S_InitStructure.CLKPOL = I2S_CLKPOL_LOW;
I2S_InitStructure.I2sMode = I2S_MODE_MASTER_TX;
I2S_Init(I2S_MASTER, &I2S_InitStructure);
I2S_InitStructure.I2sMode = I2S_MODE_SlAVE_RX;
I2S_Init(I2S_SLAVE, &I2S_InitStructure);
SPI_I2S_EnableDma(I2S_SLAVE, SPI_I2S_DMA_RX, ENABLE);
SPI_I2S_EnableDma(I2S_MASTER, SPI_I2S_DMA_TX, ENABLE);
I2S_Enable(I2S_SLAVE, ENABLE);
I2S_Enable(I2S_MASTER, ENABLE);
printf("\r\n Enable DMA2 Channel2 \r\n");
DMA_EnableChannel(I2S_MASTER_Tx_DMA_Channel, ENABLE);
printf("\r\n Enable DMA1 Channel4 \r\n");
DMA_EnableChannel(I2S_SLAVE_Rx_DMA_Channel, ENABLE);
printf("\r\n Wait for DMA2 channel2 transfer complete \r\n");
while (!DMA_GetFlagStatus(I2S_MASTER_Tx_DMA_FLAG, DMA2));
while (!DMA_GetFlagStatus(I2S_SLAVE_Rx_DMA_FLAG, DMA1));
printf("\r\n Check the correctness of written data \r\n");
TransferStatus = Buffercmp(I2S_SLAVE_Buffer_Rx, (uint16_t*)I2S_MASTER_Buffer_Tx, BufferSize);
printf("\r\n I2S_SLAVE_Buffer_Rx\r\n");
for(i = 0; i < 32; i++)
{
if(i % 8 == 0)
{
printf("\r\n:");
}
printf(" 0x%02X", I2S_SLAVE_Buffer_Rx[i]);
}
if(PASSED)
{
printf("\r\n OK !\r\n");
}
else
{
printf("\r\n NO !\r\n");
}
while (1)
{
}
}
经程序的编译和下载,其测试结果如图4所示,说明程序是卡在数据传送过程中,并没有实现数据的传递任务。
图4 测试结果
随后,在网上发现了一位网友的成功,他在板载资源的基础上实现了音频的录放功能,于是抱着尝试的心理进行了一下测试。
该设计的思想是:以按键来控制音频的录制、保存和播放,具体的功能分配是:
S3:录制/暂停、S4:保存录音、S5:播放
所录制的音频数据是被存放到flash存储器中,因此在使用时需将J29、J30、J31、J32、J46及J47用跳线帽连接,见图5所示。
图5 实际连线
此外,为了便于观察还使用串口来输出工作的状态信息,串口的波特率为115200bps 。
在对程序编译和下载后,器测试结果如图6至图8所示。
图6 准备状态及录制
图7 播放过程中
图8 完成播放
经实际测试,该设计还是十分成功的,弥补了例程的不足,从中学到了不少实用的知识,在此深表感谢!
为了更便于所用,又为其添加了OLED屏显示界面,见图9所示。
实现界面显示效果的函数为:
void OLED_jm(void)
{
OLED_config();
OLED_Init();
OLED_Clear();
OLED_ShowString(0,5,"S3: S4: S5: ",16);
OLED_ShowCHinese(8,0,12);
OLED_ShowCHinese(24,0,13);
OLED_ShowCHinese(40,0,0);
OLED_ShowCHinese(56,0,1);
OLED_ShowCHinese(72,0,4);
OLED_ShowCHinese(90,0,5);
OLED_ShowCHinese(106,0,17);
OLED_ShowCHinese(24,5,18);
OLED_ShowCHinese(64,5,16);
OLED_ShowCHinese(104,5,15);
}
图9 显示界面
- 2025-02-16
-
回复了主题帖:
【N32A455 车规MCU开发板测评】气体传感器检测酒精含量
okhxyyo 发表于 2025-2-13 14:08
不错不错~~
感谢您地鼓励!!!
- 2025-02-13
-
发表了主题帖:
【N32A455 车规MCU开发板测评】气体传感器检测酒精含量
N32A455基于 32位 ARM Cortex-M4F内核,其最高主频可达144MHz,内置了4 个 12位的ADC,其采集速度达 4.7Msps,可配置为 12/10/8/6位采集模式。若以6位模式采样,则可达8.9Msps。它有 38 路外部单端输入通道,且支持差分模式。
其中,ADC1 支持 9 个外部通道,ADC2 支持 12 个外部通道,ADC3 支持 15 个外部通道,ADC4 支持 13 个 外部通道,并且 ADC 的输入时钟最大频率为达 80MHz,所有模拟接口支持 1.8~3.6V 全电压工作。
为了便于测试,还板载了一个电位器,所连接的引脚为PB15,见图1所示。
图1 电位器及连接关系
为便于观察,特为其配置了TFT显示屏。之所以将有了配置的LCD5110屏换为TFT显示屏,是因为在其它地方显示正常的LCD5110一旦放到此处,会出现显示杂乱甚至不显示的问题。
该显示屏与原LCD5110屏占用的引脚相同,仍是PE2至PE6,具体连接情况为:
CS ---PE2
REST ---PE3
DC ---PE4
SDI ---PE5
SCK ---PE6
所用引脚的配置函数为:
void LCD_config(void)
{
GPIO_InitType GPIO_InitStructure;
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);
GPIO_InitStructure.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOE, &GPIO_InitStructure);
}
该显示屏的初始化函数为:
void TFT_Init(void)
{
LCD_REST_Low();
delay1();
LCD_REST_High();
delay1();
LCD_CS_Low();
LCD_WR_REG(0xCB);
LCD_WR_DATA8(0x39);
LCD_WR_DATA8(0x2C);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x34);
LCD_WR_DATA8(0x02);
LCD_WR_REG(0xCF);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0XC1);
LCD_WR_DATA8(0X30);
LCD_WR_REG(0xE8);
LCD_WR_DATA8(0x85);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x78);
LCD_WR_REG(0xEA);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x00);
LCD_WR_REG(0xED);
LCD_WR_DATA8(0x64);
LCD_WR_DATA8(0x03);
LCD_WR_DATA8(0X12);
LCD_WR_DATA8(0X81);
LCD_WR_REG(0xF7);
LCD_WR_DATA8(0x20);
LCD_WR_REG(0xC0);
LCD_WR_DATA8(0x23);
LCD_WR_REG(0xC1);
LCD_WR_DATA8(0x10);
LCD_WR_REG(0xC5);
LCD_WR_DATA8(0x3e);
LCD_WR_DATA8(0x28);
LCD_WR_REG(0xC7);
LCD_WR_DATA8(0x86);
LCD_WR_REG(0x36);
LCD_WR_DATA8(0x48);
LCD_WR_REG(0x3A);
LCD_WR_DATA8(0x55);
LCD_WR_REG(0xB1);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x18);
LCD_WR_REG(0xB6);
LCD_WR_DATA8(0x08);
LCD_WR_DATA8(0x82);
LCD_WR_DATA8(0x27);
LCD_WR_REG(0xF2);
LCD_WR_DATA8(0x00);
LCD_WR_REG(0x26);
LCD_WR_DATA8(0x01);
LCD_WR_REG(0xE0);
LCD_WR_DATA8(0x0F);
LCD_WR_DATA8(0x31);
LCD_WR_DATA8(0x2B);
LCD_WR_DATA8(0x0C);
LCD_WR_DATA8(0x0E);
LCD_WR_DATA8(0x08);
LCD_WR_DATA8(0x4E);
LCD_WR_DATA8(0xF1);
LCD_WR_DATA8(0x37);
LCD_WR_DATA8(0x07);
LCD_WR_DATA8(0x10);
LCD_WR_DATA8(0x03);
LCD_WR_DATA8(0x0E);
LCD_WR_DATA8(0x09);
LCD_WR_DATA8(0x00);
LCD_WR_REG(0XE1);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x0E);
LCD_WR_DATA8(0x14);
LCD_WR_DATA8(0x03);
LCD_WR_DATA8(0x11);
LCD_WR_DATA8(0x07);
LCD_WR_DATA8(0x31);
LCD_WR_DATA8(0xC1);
LCD_WR_DATA8(0x48);
LCD_WR_DATA8(0x08);
LCD_WR_DATA8(0x0F);
LCD_WR_DATA8(0x0C);
LCD_WR_DATA8(0x31);
LCD_WR_DATA8(0x36);
LCD_WR_DATA8(0x0F);
LCD_WR_REG(0x11);
delay1();
LCD_WR_REG(0x29);
LCD_WR_REG(0x2c);
}
ADC的初始化函数为:
void ADC_Initial(ADC_Module* ADCx)
{
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = DISABLE;
ADC_InitStructure.ContinueConvEn = DISABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 1;
ADC_Init(ADCx, &ADC_InitStructure);
ADC_Enable(ADCx, ENABLE);
while(ADC_GetFlagStatusNew(ADCx,ADC_FLAG_RDY) == RESET);
ADC_StartCalibration(ADCx);
while (ADC_GetCalibrationStatus(ADCx));
}
读取检测值的函数为:
uint16_t ADC_GetData(ADC_Module* ADCx, uint8_t ADC_Channel)
{
uint16_t dat;
ADC_ConfigRegularChannel(ADCx, ADC_Channel, 1, ADC_SAMP_TIME_239CYCLES5);
ADC_EnableSoftwareStartConv(ADCx, ENABLE);
while(ADC_GetFlagStatus(ADCx, ADC_FLAG_ENDC)==0){
}
ADC_ClearFlag(ADCx, ADC_FLAG_ENDC);
ADC_ClearFlag(ADCx, ADC_FLAG_STR);
dat=ADC_GetDat(ADCx);
return dat;
}
对ADC1通道6的数据采集与显示主程序为:
int main(void)
{
uint16_t V;
LCD_config();
RCC_Configuration();
GPIO_Configuration();
ADC_Initial(ADC1);
TFT_Init();
LCD_Clear(WHITE);
BACK_COLOR=WHITE;
POINT_COLOR=RED;
LCD_ShowString(30,30,"Channel_06:");
LCD_ShowString(30,60,"Channel_06: mV");
while (1)
{
ADC1ConvertedValue[0]=ADC_GetData(ADC1,ADC1_Channel_06_PC0);
V=ADC1ConvertedValue[0];
LCD_ShowNum(126,30,V,4);
V=V*3300/4096;
LCD_ShowNum(126,60,V,4);
Delay(0X8FFFFF);
}
}
经程序的编译与下载,在电位器输出引脚PB15与读取引脚PC0相连接的情况下,其测试效果如图2至图4所示。
图2 最小值
图3 调节值
图4 最大值
若将PC0连接到气体传感器上,则可进行酒精含量检测,其连接与检测情况如图5至图7所示。
可见,在常规状态其检测值为85mV;在检测酒精时为413mV;在接近电路板时为116mV。
图5 常规状态
图6 酒精含量检测
图7 接近电路板
- 2025-02-10
-
发表了主题帖:
【N32A455 车规MCU开发板测评】W25Q128读写与构建图库
N32A455配有3路SPI接口,并允许芯片与外部设备以半/全双工、同步、串行方式通信。此接口可以被配置成主模式,并为外部从设备提供通信时钟(SCK)。
此外,还板载了一路SPI FLASH(W25Q128),借由SPI1进行工作,其电路如图1所示。要求注意的是,在使用必须通过跳线来连接J29、 J30、 J31、 J32与PA4、PA5、PA6、PA7。
起初没太注意,结果出现了读ID异常的问题,见图2所示。
图1 引脚连接
图2 未连接状态
使用官方的例程,可对SPI FLASH进行读、写、擦除等操作,其主程序为:
int main(void)
{
log_init();
LedInit(GPIOE, LED1 | LED2);
LedOff(GPIOE, LED1 | LED2);
sFLASH_Init();
FlashID = sFLASH_ReadID();
printf("Read ID=0x%06x\r\n",FlashID);
if ((FlashID == sFLASH_ID)||(FlashID == sFLASH_W25Q128_ID_DTR))
{
LedOn(GPIOE, LED1);
sFLASH_EraseSector(FLASH_SectorToErase);
sFLASH_WriteBuffer(Tx_Buffer, FLASH_WriteAddress, BufferSize);
sFLASH_ReadBuffer(Rx_Buffer, FLASH_ReadAddress, BufferSize);
TransferStatus1 = Buffercmp(Tx_Buffer, Rx_Buffer, BufferSize);
if(PASSED == TransferStatus1)
printf("Flash write OK.\r\n");
else
printf("Flash write fail.\r\n");
sFLASH_EraseSector(FLASH_SectorToErase);
sFLASH_ReadBuffer(Rx_Buffer, FLASH_ReadAddress, BufferSize);
for (Index = 0; Index < BufferSize; Index++)
{
if (Rx_Buffer[Index] != 0xFF)
{
TransferStatus2 = FAILED;
break;
}
}
if(PASSED == TransferStatus2)
printf("Sector erase OK.\r\n");
else
printf("Sector erase fail.\r\n");
}
else
{
LedOn(GPIOE, LED2);
printf("Read ID fail.\r\n");
}
while (1)
{
}
}
经程序的编译与下载,其测试效果如图3所示。
图3 测试效果
具备了W25Q128的读写功能,可以用它做点啥呢?
那就是可以扩展存储空间,如做个字库或是图库啥的,因为当需要显示多幅图片时,单凭程序的存储空间是无法完成保存的。此时,可通过多次转存将程序中的图像数据转存到W25Q128内,在需要时即可连续从W25Q128中读取数据,进而实现多幅图片的显示。
在测试构建图库前,先进行了图片显示功能的测试,其主程序为:
int main(void)
{
TFT_config();
TFT_Init();
LCD_Clear(WHITE);
show_pic(gImage_AIK);
BACK_COLOR=WHITE;
POINT_COLOR=RED;
LCD_ShowString(20,16,"N32A455");
LCD_DrawLine(0, 40, 239,40);
POINT_COLOR=GREEN;
LCD_ShowNum();
}
经程序的编译与下载,其显示效果如图4所示。
图4 显示效果
有了图片显示功能的支持,实现单幅图片存储与再现的主程序为:
int main(void)
{
uint32_t i,j,k,dz=0;
uint8_t pic;
log_init();
TFT_config();
TFT_LED_High();
TFT_Init();
LCD_Clear(WHITE);
sFLASH_Init();
FlashID = sFLASH_ReadID();
if ((FlashID == sFLASH_ID)||(FlashID == sFLASH_W25Q128_ID_DTR))
{
dz=0x700000;
for (uint32_t i = 0; i < 38; i++)
{
sFLASH_EraseSector(dz);
dz=dz+0x1000;
}
Address_set(0,0,LCD_W-1,LCD_H-1);
dz=0x700000;
k=0;
for ( j = 0; j < 600; j++)
{
for ( i = 0; i < 256; i++)
{
Tx_Buffer[i]= gImage_AIK[k];
k=k+1;
}
sFLASH_WriteBuffer(Tx_Buffer, dz, 256);
dz=dz+0x100;
}
dz=0x700000;
for (j = 0; j < 600; j++)
{
sFLASH_ReadBuffer(Rx_Buffer,dz, 256);
for (i = 0; i < 256; i++)
{
pic=Rx_Buffer[i];
LCD_WR_DATA8(picH);
}
dz=dz+0x100;
}
while (1);
}
经程序的编译与下载,其显示效果如图4所示,说明程序设计正确。后续要存储多幅图片,只需更新图片数组的内容及指定W25Q128存储和读取的首地址即可。
图5 再现效果
再现速度之快,可见图6所示。
图6 刷新速度
- 2025-02-08
-
回复了主题帖:
读书入围名单:《Python编程:从入门到实践(第3版)》
个人信息无误,确认可以完成阅读分享计划
-
回复了主题帖:
【新年花灯】基于点阵显示板的灵蛇献瑞
秦天qintian0303 发表于 2025-2-7 17:26
又是一种新年花灯,大家手里真是各种存货啊
嗯,该去继续积累了。
- 2025-02-07
-
发表了主题帖:
【新年花灯】基于点阵显示板的灵蛇献瑞
本帖最后由 Lily李 于 2025-2-8 12:57 编辑
新年点灯咱是认真的,论数量它可是16*16*4个,论移动它是整体搬迁呀!
[localvideo]c2245b76b97484a47d5523325b47f188[/localvideo]
-
回复了主题帖:
【N32A455 车规MCU开发板测评】以串口发送数据
Jacktang 发表于 2025-2-7 07:50
直接使用调试用串口是比较方便
的确是这样
- 2025-02-06
-
发表了主题帖:
【N32A455 车规MCU开发板测评】以串口发送数据
在通常的情况下,对采集的数据需上传到上位机以供处理。
为了测试的方便,直接使用调试用串口,见图1所示。
图1 调试口
在使用时,需短接J2的引脚7和引脚8相连,引脚9和引脚10相连。
对串口1的配置函数为:
void USART1_Config(void)
{
GPIO_InitType GPIO_InitStructure;
USART_InitType USART_InitStructure;
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1 | RCC_APB2_PERIPH_GPIOA, ENABLE);
/* USART1 GPIO config */
/* Configure USART1 Tx (PA.09) as alternate function push-pull */
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
/* Configure USART1 Rx (PA.10) as input floating */
GPIO_InitStructure.Pin = GPIO_PIN_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
/* USART1 work mode*/
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO ;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
USART_Init(USART1, &USART_InitStructure);
USART_Enable(USART1, ENABLE);
}
为支持打印输出功能所配置的函数为:
int fputc(int ch, FILE* f)
{
USART_SendData(USART1, (uint8_t)ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXDE) == RESET) ;
return (ch);
}
在显示功能的基础上,实现数据采集与发送功能的主程序为:
int main(void)
{
uint16_t V;
LCD_config();
RCC_Configuration();
GPIO_Configuration();
ADC_Initial(ADC1);
LCD_LED_High();
TFT_Init();
LCD_Clear(WHITE);
BACK_COLOR=WHITE;
POINT_COLOR=RED;
LCD_ShowString(30,30,"Channel_06:");
LCD_ShowString(30,60,"Channel_06: mV");
USART1_Config();
while (1)
{
ADC1ConvertedValue[0]=ADC_GetData(ADC1,ADC1_Channel_06_PC0);
V=ADC1ConvertedValue[0];
LCD_ShowNum(126,30,V,4);
V=V*3300/4096;
LCD_ShowNum(126,60,V,4);
printf("\r\n Temperature = %d mV \r\n",V);
Delay(0X8FFFFF);
}
}
经程序的编译与下载,其串口发送功能的测试效果如图2所示。
图2 测试效果