发 帖  
[经验]

【正点原子STM32H7R3开发套件试用体验】桌面化多传感器管理与控制

2024-12-8 15:00:50  2565 正点原子
0
jf_01200635 2024-12-9 08:19:21
1回复

举报

jinglixixi 2024-12-12 10:01:22
板凳
回复

举报

jinglixixi 2024-12-12 19:17:10
3#

AP3216C距离传感器:


AP3216C 是敦南科技推出的一款三合一环境传感器, 它包含了:数字环境光传感器(ALS)、接近传感器(PS)和一个红外 LED(IR)。该芯片通过 IIC 接口和 MCU 连接,并支持中断(INT)输出。


AP3216C 的特点如下:

(1)IIC 接口,支持高达 400KHz 通信速率.

(2)支持多种工作模式(ALS、PS+IR、ALS+PS+IR 等)

(3)内置温度补偿电路

(4)工作温度支持-30~80℃

(5)环境光传感器具有 16 位分辨率

(6)接近传感器具有 10 位分辨率

(7)红外传感器具有 10 位分辨率

(8)超小封装(4.12.41.35mm)








因为以上的特性,AP3216C 被广泛应用于智能手机上面,用来检测光强度(自动背光控制),和接近开关控制(听筒靠近耳朵,手机自动灭屏功能)。AP3216C 的框图如图1所示。


image.png

图1 结构框图


该传感器在开发板上的电路如图2所示,所用引脚为PF0和PF1。
image.png

图2 传感器电路


经程序的编译与下载,其测试结果如图3所示。
image.png

图3 测试结果


其中,ALS表示光照强度(+)、PS表示接近距离(-)、IR表示红外光强。


在测试过程中,各项数值在一定范围内不断地波动,当用手遮挡或靠近AP3216C 传感器时,ALS和PS的数据变化比较突出。在靠近 AP3216C 传感器时,由于光线被遮挡的原因其ALS值会变小,而PSS值会变大。在遮挡AP3216C 传感器时,ALS值为0,而PSS值为1023。


在通常情况下,使用光照强度传感器其值会十分稳定,后面会尝试在开发板上添加该传感器的检测功能。




回复

举报

jinglixixi 2024-12-13 10:45:07
4#

QMC6308 磁力计检测


QMC6308 是一款 QST(上海矽睿)的三轴地磁传感器,经内部信号处理,以IIC 接口进行输出。QMC6308 提供的输出信号与它在 XYZ 方向上测量的磁场成比例,如需要消除比例因子,则需要用户自行校准。

QMC6308 主要特点如下:

(1)测量范围:最大±30 高斯

(2)高分辨率:0.15μT/LSB(X/Y 轴),0.25μT/LSB(Z 轴)

(3)高灵敏度:三个轴正交:90°±1,灵敏度:1000 LSBs/Gauss

(4)工作温度范围:-40~ +85℃

(5)供电电压:1.65~1.95V

(6)16 位 ADC 采样

(7)内部带有温度传感器

(8)支持中断









QMC6308 传感器的检测轴如图1 所示,其内部结构如图2所示。
image.png

图1 检测轴及方向


image.png

图2 内部结构


QMC6308 磁力计与开发板的连接关系如图3所示,由于使用的是I2C总线,由此也是连接到PF0和PF1引脚。


image.png

图3 电路连接


经程序的编译与下载,其检测效果如图4所示。
image.png

图4 检测效果


当在水平面内由南向北移动开发板时,MagX值会变大;


当在水平面内由东向西移动开发板时,MagY值会变小;


当在垂直反向由上向下移动开发板时,MagZ值会变大;


当开发板由南向北移动顺时针反向旋转时,Angle值会产生由小变大---由大变小---由大变小---由小变大的过程。


据资料介绍在数据偏差较大时,可进行校准处理,即水平放置开发板,然后按下KEY0以进入校准模式,随后将开发板在水平面内缓慢旋转2~3圈,在按下KEY_UP退出校准模式。




回复

举报

jinglixixi 2024-12-14 09:55:52
5#

QMI8658A 六轴传感器检测:


QMI8658A 是一款针对大众市场的高性价比六轴传感器,它具有功耗低、噪声低、封装小的特点。


QMI8658A 内部集成有 3 轴陀螺仪和 3 轴加速度计;可以通过 I3C、I2C 和 3 线或 4 线 SPI的接口和MCU进行数据交互,传输速率可达 400kHZ/s。陀螺仪的角速度测量范围最高达±2048°/S,具有良好的动态响应特性。加速度计的测量范围最大为±16g(g 为重力加速度),静态测量精度高。广泛应用于智能手机、游戏控制器、遥控器和汽车安全系统等场景。


QMI8658A 的特点如下:

(1)陀螺仪 13 mdps/Hz 的低噪声、低延迟、宽带宽

(2) 150μg/Hz 的加速度计噪声

(3)自带一个温度数字传感器

(4)可编程数字滤波器

(5)集成计步器、轻拍、任意运动、移动、显著运动检测

(6)自带 1536 字节 FIFO 可用于缓冲传感器数据降低系统功耗

(7)超小封装尺寸:2.5×3.0×0.86mm(LGA)







QMI8658A 传感器的检测轴如图1 所示,其内部框图如图2 所示。
image.png

图1 检测轴及其方向


image.png

图2 结构框图


QMI8658A 六轴传感器与开发板的连接关系如图3所示,所使用的引脚为PF0、PF1和PE3。


image.png

图3 电路连接


经程序的编译与下载,其检测效果如图4和图5所示。
image.png

图4 串口信息


image.png

图5 检测效果


其中,Temp指示温度值、Pitch指示俯仰角、Roll指示横滚角、Yaw指示航向角。


若使用软件ANO_TC 匿名科创地面站 v4.51来接收开发板所上传的数据,则可以图形化的方式来显示飞行姿态,见图6所示。这是对6轴传感器检测中的最大收获,发现了一种可直观展示数据变化的工具。


image.png

图6 飞行姿态




回复

举报

jinglixixi 2024-12-14 23:02:11
6#

WS2812B灯光秀


WS2812B 是一款单线传输三通道(RGB)驱动控制电路与发光电路于一体的智能外控LED 光源。产品内含有信号解码模块、数据缓冲器、内置恒流电路及 RC 振荡器;内部集成电流增益控制模块,CMOS 制程,低压、低耗电;三通道恒流驱动器默认输出 19mA,采用单线输出方式,串接各晶片之输出动作同步;上电默认不亮灯。


数据协议采用单极性归零码的通讯方式,单线传输LED 驱动控制专用芯片,同时芯片内


置的电流增益调节功能,可设置电流1.75mA~19mA,共 16 个电流增益等级;PWM 信号刷新率高达 4KHz,显示更趋细腻平滑,解决拍摄画面暗条纹问题,非常适合高速移动产品的使用。


200us 以上的复位时间,出现中断也不会引起误复位,可以支持更低频率、价格便宜的 MCU。


主要应用领域:消费类电子产品、LED 全彩发光字灯串、电脑及周边设备、游戏设备以及各种电器设备。


WS2812B 的特点如下:


(1)外观尺寸:2.01.80.8mm。


(2)颜色:红光、绿光、蓝光。


(3)胶体:无色透明。


(4)EIA 规范标准包装。


(5)环保产品,符合ROHS 要求。


(6)适用于自动贴片机。


(7)适用于红外线回流焊制程。


WS2812B 的内部结构如图1所示,其电路连接如图2所示。
image.png


图1 内部结构


image.png


图2 电路连接


实现彩灯效果的主程序为:


int main(void){
    uint8_t key, t = 0;
    uint8_t k, i, j = 0;
    uint32_t rgbled_buf[10];
    sys_mpu_config();
    sys_cache_enable();
    HAL_Init();
    sys_stm32_clock_init(300, 6, 2);
    delay_init(600);
    usart_init(115200);
    led_init();
    key_init();
    hyperram_init();
    ws2812b_init();
    delay_ms(10);   
    while (1)
    {
        if(t % 100 == 0)
        {
            for(i = 0; i < LED_NUM; i++)
            {
                rgbled_buf[i] = g_grb888_color[j % LED_NUM];
            }
            for(k = 1; k <= LED_NUM; k++)
            {
                ws2812b_display(k, rgbled_buf);
                delay_ms(50);
            }
            j++;
            t = 0;            
        }
        t++;
        delay_ms(10);
    }
}

经程序的编译与下载,其检测效果如图3和图4所示。
image.png


图3 显示粉色


image.png


图4 显示亮蓝色


彩色灯链


当使用一个60点位的WS2812灯链时,需对定义的参数进行如下的修改:


#define LED_NUM             60


所实现的效果如图5和图6所示。
image.png


图5 效果1


image.png


图6 效果2


演示视频:





回复

举报

jinglixixi 2024-12-15 12:01:34
7#

DS18b20温度检测:


DS18B20 是由 DALLAS 半导体公司推出的一种“单总线”接口的温度传感器。与传统的


热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器。单总线结构具有简洁且经济的特点,可使用户轻松地组建传感器网络,从而为测量系统的构建引入全新的概念,其测试温度范围为: - 55  ~ +125℃,精度为 :± 0.5℃ 。

现场温度直接以单总线的数字方式传输,大大提高了系统的抗干扰性。它能直接读出被测温度,其工作电压范围在:3 ~ 5.5V 。


其内部结构如图1 所示,器件的连接关系如图2所示。
image.png

图1 内部结构


image.png

图2 连接关系


由于开发板并未随机配备DS18B20,因此要进行测试和使用需自行购置。在插接DS18B20后,其连接状态如图3所示。


image.png

图3 实物连接


经程序的编译和下载,其运行效果如图4所示。
image.png

图4 运行效果




回复

举报

jinglixixi 2024-12-15 12:49:02
8#

DHT22温度检测:


在STM32H7R3开发板上配有DHT11温度传感器的接口,但并未随机配备该器件。


DHT11 是一款温湿度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个NTC 测温元件,并与一个高性能 8 位单片机相连接。通过与单片机等微处理器的简单电路连接就能够实时的采集本地湿度和温度。


DHT11 与单片机之间能采用简单的单总线进行通信,仅仅需要一个 I/O 口。传感器内部湿度和温度数据有40Bit能一次性传给单片机,数据采用校验和的方式进行校验,以有效地保证数据传输的准确性。DHT11 功耗很低,5V 电源电压下,工作平均最大电流 0.5mA。


DHT11 的技术参数如下:


(1)工作电压范围:3.3V ~ 5.5V


(2)工作电流:平均 0.5mA


(3)输出:单总线数字信号


(4)测量范围:湿度 5 ~ 95%RH,温度-20 ~ 60℃。


(5)精度:湿度±5%,温度±2℃。


(6)分辨率:湿度 1%,温度 0.1℃。


DHT11 的管脚排列如图1 所示,电路连接关系如图2所示。
image.png


图1 引脚排列


image.png


图2 连接关系


由于手头并没有该器件,故打算以DHT22 来替代DHT11,DHT22 的技术参数及器件外观如图3所示。


image.png


图3 技术参数及器件外观


与DHT11不同,DHT22对40位数据有着自己的含义分配。


设收到的40 位数据为:


0000 0010


1001 0010


0000 0001


0000 1101


1010 0010


按照其排列顺序,其作用位:


湿度高8 位


湿度低8 位


温度高8 位


温度低8 位


校验位


计算校验位的方法位:


0000 0010+1001 0010 +0000 0001+0000 1101= 1010 0010(校验位)


在接收数据正确的情况下:


湿度:0000 0010 1001 0010 = 0292H (十六进制)= 2×256 + 9×16 + 2 = 658  => 湿度 = 65.8%RH


温度:0000 0001 0000 1101 = 10DH(十六进制) = 1×256 + 0×16 + 13 = 269  => 温度= 26.9℃


据此,修改后的DHT22读取数据函数为:


uint8_t dht22_read_data(uint8_t *temp, uint8_t *humi)
{
    uint8_t buf[5];
    uint8_t i;
    uint16_t V;
    dht11_reset();
    if (dht22_check() == 0)
    {
        for (i = 0; i < 5; i++)
        {
            buf[i] = dht22_read_byte();
        }
        if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
        {
                   V=(buf[0]*256+buf[1])/10;  
                  *humi = V;
                   V=(buf[2]*256+buf[3])/10;
                  *temp = V;
        }
    }
    else
    {
        return 1;
    }
    return 0;
}

由于DHT22的检测间隔时间为2秒,故检测温度的主程序为:


int main(void)
{
    uint8_t t = 0;
    uint8_t temperature;
    uint8_t humidity;
    sys_mpu_config();
    sys_cache_enable();
    HAL_Init();
    sys_stm32_clock_init(300, 6, 2);
    delay_init(600);
    usart_init(115200);
    led_init();
    hyperram_init();
    lcd_init();   
    lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
    lcd_show_string(30, 70, 200, 16, 16, "DHT22 TEST", RED);      
    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    while (dht22_init())
    {
        lcd_show_string(30, 110, 200, 16, 16, "DHT22 Error", RED);
        delay_ms(200);
        lcd_fill(30, 110, 239, 130 + 16, WHITE);
        delay_ms(200);
    }
    lcd_show_string(30, 110, 200, 16, 16, "DHT22 OK", RED);
    lcd_show_string(30, 130, 200, 16, 16, "Temp:  C", BLUE);
    lcd_show_string(30, 150, 200, 16, 16, "Humi:  %", BLUE);
    while (1)
    {
        if (t %200 == 0)
        {
            Dht22_read_data(&temperature, &humidity);
            lcd_show_num(30 + 40, 130, temperature, 2, 16, BLUE);
            lcd_show_num(30 + 40, 150, humidity, 2, 16, BLUE);
        }
        delay_ms(10);
        t++;
       if (t == 20)
        {
            t = 0;
           LED0_TOGGLE();
        }
    }
}

经程序的编译与下载,其检测效果如图5所示。


由于DHT11与DS18B20使用的是同一个接口,但DHT11的引脚比DS18B20要粗,故无法直接利用该接口来连接,只能通过导线来进行连接,如图4所示。
image.png

图4 器件连接


image.png

图5 运行效果




回复

举报

jinglixixi 2024-12-15 23:19:14
9#

RTC电子时钟:


STM32H7R3 的实时时钟(RTC)相对于 STM32F1 来说,改进了不少,它配了日历功能。RTC 是一个独立的 BCD 定时器/计数器。RTC 提供一个日历时钟(包含年月日时分秒信息)、两个可编程闹钟(ALARM A 和 ALARM B)中断,以及一个具有中断功能的周期性可编程唤醒标志。此外,RTC 还包含用于管理低功耗模式的自动唤醒单元。它的两个32 位寄存器(TR 和 DR)包含二进码十进数格式 (BCD) 的秒、分钟、小时(12 或24 小时制)、星期、日期、月份和年份。此外,还可提供二进制格式的亚秒值。


STM32H7R3 的 RTC 可以自动将月份的天数补偿为 28、29(闰年)、30 和 31 天。并且还可以进行夏令时补偿。


RTC 模块和时钟配置是在后备区域,即在系统复位或从待机模式唤醒后 RTC 的设置和时间维持不变,只要后备区域供电正常,那么 RTC 将可以一直运行。但是在系统复位后,会自动禁止访问后备寄存器和 RTC,以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前, 先要取消备份区域(BKP)写保护。


RTC 的内部框图如图1 所示:
image.png

图1 内部结构


RTC 的配置步骤为:


(1)使能 RTC 时钟,并使能 RTC 及 RTC 后备寄存器写访问复位后,后备区域存在写保护,RTC 属于后备区域,所以我们需要取消后备区域写保护。同时,我们需要使能 RTC 时钟,通过 RCC_APB4ENR 寄存器中的 RTCAPBEN 位设置。而取消后备区域写保护则是通过 PWR_CR1 寄存器中的 DBP 位去设置。


HAL 库设置方法为:


__HAL_RCC_RTC_CLK_ENABLE(); /* 使能 RTC 时钟 */


HAL_PWR_EnableBkUpAccess(); /* 取消备份区域写保护 */


(2)开启外部低速振荡器 LSE,选择 RTC 时钟,并使能调用 HAL_RCC_OscConfig 函数配置开启 LSE。


调用 HAL_RCCEx_PeriphCLKConfig 函数选择 RTC 时钟源。


使能 RTC 函数为:__HAL_RCC_RTC_ENABLE。


(3)初始化 RTC,设置 RTC 的分频,以及配置 RTC 参数在 HAL 中,通过 HAL_RTC_Init 函数配置 RTC 分频系数,以及 RTC 的工作参数。


注意:该函数会调用:HAL_RTC_MspInit 函数来完成对 RTC 的底层初始化,包括:RTC时钟使能、时钟源选择等。


(4)设置 RTC 的时间


调用 HAL_RTC_SetTime 函数设置 RTC 时间,该函数实际设置时间寄存器 RTC_TR 的相关位的值。


(5)设置 RTC 的日期


调用 HAL_RTC_SetDate 函数设置 RTC 的日期,该函数实际设置日期寄存器 RTC_DR 的相关位的值。


(6)获取 RTC 当前日期和时间


调用 HAL_RTC_GetTime 函数获取当前 RTC 时间,该函数实际读取 RTC_TR 寄存器,然后将值存放到相应的结构体中。


调用 HAL_RTC_GetDate 函数获取当前 RTC 日期,该函数实际读取 RTC_DR 寄存器,然后将值存放到相应的结构体中。


通过以上 6 个步骤,就完成了对 RTC 的配置,RTC 即可正常工作,而且这些操作不是每次上电都必须执行的,可以视情况而定。当然,我们还可以唤醒中断、闹钟等。


经程序的编译与下载,其测试结果如图2所示。
image.png

图2 显示效果




回复

举报

jinglixixi 2024-12-16 10:50:24
10#

A/D数据采集:


STM32H7R3xx 系列有 2 个 ADC,都可以独立工作,其中 ADC1 和 ADC2 还可以组成双重模式(提高采样率)。


STM32H7R3 的 ADC 主要特性如下:


(1)可配置 12 位、10 位、8 位、6 位分辨率,降低分辨率可以缩短转换时间,转换时间越短,可以做到的采样率就越高。

(2)每个 ADC 支持多达 19 个的采集通道,其中有 17 个外部通道和 2 个内部通道。17 个外部通道中,有 6 路快速通道和 11 路慢速通道,慢速和快速的区别主要是支持的最高采样率不同,慢速通道要比快速通道低。这些通道的 A/D 转换可以单次、连续、扫描或间断模式执行。

(3)ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。

(4)ADC 具有四条专用的内部通道,一路用于内部温度传感器(VSENSE)、一路用于内部参考电压、一路用于监控外部 VBAT 电源引脚、一道用于监控内部 VDDCORE 电源。

(5)支持过采样,过采样比 2 ~ 256x 可调,可编程数据移位高达 8 位。

(6)每个 ADC 支持三路模拟看门狗。

(7)支持单独输入和差分输入(可按通道进行编程)。

(8)ADC 输入范围:VREF– ≤ VIN ≤ VREF+。由 VREF- 、VREF+ 、VDDA 和 VSSA 这四个外部引脚决定。一般我们把VSSA 和 VREF- 接地,把 VREF+ 和 VDDA 接到 3.3V,所以得到 ADC 的输入电压范围是:0~3.3V。注意不要接超出这个范围的电压进来,否则容易烧坏芯片。

(9)自校准(偏移校准和线性度校准)。

(10)最多 4 条注入转换序列,16 条常规转换序列。









ADC(仅限 ADC1 或 ADC2)的结构框图如图1所示,用于检测的模拟信号电路如图2所示。


image.png

图1 结构框图


image.png

图2 模拟信号电路


在进行模拟信号检测时,需将P14接口的引脚2和引脚3相短接。通过调节电位器,即可改变检测的电压值。


当然,也可用杜邦线将一端接到P14的 ADC 排针上,另外一端接到待测试的信号输出端。但一定要保证测试点的电压在0~3.3V 的电压范围,否则可能烧坏ADC,甚至是整个主控芯片。


经程序的编译与下载,其测试结果如图2和图3所示。


image.png

图2 检测效果1


image.png

图3 检测效果2


后续打算再为A/D数据采集添加一个波形曲线绘制功能,以便更加直观的展示数据的变换趋势。


回复

举报

jinglixixi 2024-12-16 18:28:47
11#

IR红外遥控测试:


红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器所广泛采用,并越来越多的应用到计算机系统中。由于红外线遥控不具备像无线电遥控那样的穿过障碍物去控制对象的能力,所以,在设计红外线遥控器时,不必像无线电遥控器那样,每套(发射器和接收器)要有不同的遥控频率或编码(否则,就会隔墙控制或干扰邻居的家用电器),所以同类产品的红外线遥控器,可以使用相同的遥控频率或编码,而不会出现遥控信号“串门”的情况。这对于大批量生产以及在家用电器上普及红外线遥控提供了极大的方便。由于红外线为不可见光,因此对环境影响很小,再加上红外光波长远小于无线电波的波长,所以红外线遥控不会影响其他家用电器,也不会影响临近的无线电设备。


红外遥控接收头与开发板的连接关系如图1所示:
image.png

图1 接口电路


在红外遥控设备中,多采用NEC 协议。在该协议中数据‘0’或者‘1’有着相应的要求。


其中:


发送协议数据‘0’ = 发射载波信号 560us + 不发射载波信号 560us


发送协议数据‘1’ = 发射载波信号 560us + 不发射载波信号 1680us


红外发射器的位定义如图2所示:
image.png

图2 红外发射器位定义


接收协议数据‘0’ = 560us 低电平 + 560us 高电平


接收协议数据‘1’ = 560us 低电平 + 1680us 高电平


红外接收器的位定义如图3所示:
image.png

图3 红外接收器位定义


开发板上用于接收红外遥控信号的红外管外观如图4所示,配套的红外发送遥控器如图5所示。在使用时,遥控器需面向开发板的红外管发送信号,否则会影响接收。


image.png

图4 红外接收器


image.png

图5 红外遥控器


经程序的编译与下载,LCD屏的显示的内容如图6所示。
image.png

图6 运行效果图


当遥控器按下不同的按键时,在LCD屏上会看到不同的键值以及按键次数和对应的遥控器上的符号,见图7所示。


image.png

图7 解码成功






回复

举报

jinglixixi 2024-12-16 21:46:17
12#

触摸控制及测试:


触摸按键相对于传统的机械按键有寿命长、占用空间少、易于操作等诸多优点。大家看看


如今的手机,触摸屏、触摸按键大行其道,而传统的机械按键,正在逐步从手机上面消失。本


章,我们将给大家介绍一种简单的触摸按键:电容式触摸按键。我们将利用STM32 开发板上


的触摸按键(TPAD),来实现对 DS1 的亮灭控制。这里 TPAD 其实就是 STM32 开发板上的


一小块覆铜区域,实现原理如图1 所示。
image.png

图1 电容触摸按键原理


image.png

图2 电路连接


测试前,需进行硬件的连接(用跳线帽短接多功能端口的ADC 和 TPAD 即可)。


当使用电容触摸按键(右下角白色 LOGO,即 TPAD)时,是通过 TIM3_CH3(PB0)对电容触摸按键进行检测,以控制 DS1 的亮灭了。当LED0 闪烁时 ,表示程序在运行。


经程序的编译与下载,LCD屏的显示的内容如图3和图4所示。
image.png

图3 点亮绿灯


image.png

图4 熄灭绿灯




回复

举报

jinglixixi 2024-12-16 23:34:35
13#

OLED屏显示驱动及测试:


OLED 即有机发光二极管( Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。OLED 由于具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。


LCD 都需要背光,而 OLED 则不需要,因为它是自发光的。因此同样是显示,OLED 的效果要更好一些。以目前的技术,OLED 的尺寸还难以大型化,但是分辨率确可以做到很高。


正点原子所用的OLED 显示模块有以下特点:


(1)模块有单色和双色两种可选,单色为纯蓝色,而双色则为黄蓝双色。


(2)尺寸小,显示尺寸为 0.96 寸,而模块的尺寸仅为 27mm*26mm 大小。


(3)高分辨率,该模块的分辨率为 128*64。


(4)多种接口方式,该模块提供了总共 4 种接口包括:6800、8080 两种并行接口方式、4线 SPI 接口方式以及 IIC 接口方式(只需要 2 根线就可以控制 OLED )。


(5)不需要高压,直接3.3V 就可以工作。


在使用时一定要小心别直接接到5V 上,否则可能会烧坏模块。


OLED 模块与开发板的连接是使用OLED/CAMERA接口(P7 接口),见图1 所示。
image.png

图1 引脚排列


由于手头没有与开发板相匹配的OLED显示屏,就对手头的一款I2C接口的双色0.96’的OLED进行了驱动测试。


为适应OLED屏的引脚排列顺序和反向,准备用U29接口来连接OLED屏,从而可以直接插接使用免去连线的麻烦。


U29接口P9接口情况如图2所示,在使用时需将P9接口的3-5及4-6相短接。


image.png

图2 所用接口


为验证PM8和PM9的输出性能,使用如下的函数对引脚功能进行了配置:


void oled_init(void)
{
    //PM8  PM9
    GPIO_InitTypeDef gpio_init_struct = {0};
    __HAL_RCC_GPIOM_CLK_ENABLE();
    gpio_init_struct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
    gpio_init_struct.Pull = GPIO_PULLDOWN;
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOM, &gpio_init_struct);
}

相应的测试主程序为:


int main(void)
{
    sys_mpu_config();
    sys_cache_enable();
    HAL_Init();
    sys_stm32_clock_init(300, 6, 2);
    delay_init(600);
    oled_init();
    while (1)
    {
                HAL_GPIO_WritePin(GPIOM, GPIO_PIN_8, GPIO_PIN_SET);
                HAL_GPIO_WritePin(GPIOM, GPIO_PIN_9, GPIO_PIN_SET);                        
                delay_ms(500);                
                HAL_GPIO_WritePin(GPIOM, GPIO_PIN_8, GPIO_PIN_RESET);
                HAL_GPIO_WritePin(GPIOM, GPIO_PIN_9, GPIO_PIN_RESET);
                delay_ms(500);
    }
}

经验证,其输出效果如图3所示,说明输出能力正常。
image.png

图3 引脚测试


所设定的OLED与开发板的连接关系为:


CLK ---- PM8


DIN ---- PM9


所用引脚输出高低电平的语句定义为:


#define OLED_SCLK_Clr()  HAL_GPIO_WritePin(GPIOM, GPIO_PIN_8, GPIO_PIN_RESET)


#define OLED_SCLK_Set()  HAL_GPIO_WritePin(GPIOM, GPIO_PIN_8, GPIO_PIN_SET)


#define OLED_SDIN_Clr()  HAL_GPIO_WritePin(GPIOM, GPIO_PIN_9, GPIO_PIN_RESET)


#define OLED_SDIN_Set()  HAL_GPIO_WritePin(GPIOM, GPIO_PIN_9, GPIO_PIN_SET)


OLED的初始化函数为:


void OLED_Init(void)
{
    Write_IIC_Command(0xAE); //display off
    Write_IIC_Command(0x20); //Set Memory Addressing Mode
    Write_IIC_Command(0x10);
    Write_IIC_Command(0xb0);//Set Page Start Address for Page Addressing Mode,0-7
    Write_IIC_Command(0xc8);//Set COM Output Scan Direction
    Write_IIC_Command(0x00);//---set low column address
    Write_IIC_Command(0x10);//---set high column address
    Write_IIC_Command(0x40);//--set start line address
    Write_IIC_Command(0x81);//--set contrast control register
    Write_IIC_Command(0xdf);
    Write_IIC_Command(0xa1);//--set segment re-map 0 to 127
    Write_IIC_Command(0xa6);//--set normal display
    Write_IIC_Command(0xa8);//--set multiplex ratio(1 to 64)
    Write_IIC_Command(0x3F);//
    Write_IIC_Command(0xa4);//0xa4,Output follows RAM content;0xa5,Output ignores RAM content
    Write_IIC_Command(0xd3);//-set display offset
    Write_IIC_Command(0x00);//-not offset
    Write_IIC_Command(0xd5);//--set display clock divide ratio/oscillator frequency
    Write_IIC_Command(0xf0);//--set divide ratio
    Write_IIC_Command(0xd9);//--set pre-charge period
    Write_IIC_Command(0x22); //
    Write_IIC_Command(0xda);//--set com pins hardware configuration
    Write_IIC_Command(0x12);
    Write_IIC_Command(0xdb);//--set vcomh
    Write_IIC_Command(0x20);//0x20,0.77xVcc
    Write_IIC_Command(0x8d);//--set DC-DC enable
    Write_IIC_Command(0x14);//
    Write_IIC_Command(0xaf);//--turn on oled panel
}

显示字符串的函数为:


void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size)
{
        unsigned char j=0;
        while (chr[j]!='\\0')
        {                OLED_ShowChar(x,y,chr[j],Char_Size);
                        x+=8;
                  if(x>120){x=0;y+=2;}
                        j++;
        }
}

测试OLED屏显示功能的主程序为:


int main(void)
{
    sys_mpu_config();
    sys_cache_enable();
    HAL_Init();
    sys_stm32_clock_init(300, 6, 2);
    delay_init(600);
    led_init();
    oled_config();
    OLED_Init();
    OLED_Clear();
    OLED_ShowString(0,0,"STM32H7R3 TEST",16);
    OLED_ShowString(0,2,"OLED DISPLAY",16);
    OLED_ShowString(0,4,"jinglixixi",16);
    OLED_ShowString(0,6,"2024.12.18",16);
    while (1)
    {
        LED0(0);
        LED1(0);
        delay_ms(500);
        LED0(1);
        LED1(1);
        delay_ms(500);
    }
}

经程序的编译与下载,OLED屏的显示效果如图4所示,说明显示正常。


image.png

图4 显示效果




回复

举报

jinglixixi 2024-12-17 10:09:07
14#

NTC温度检测:


NTC(负温度系数)热敏电阻是一种热敏性半导体电阻器,其电阻值随着温度的升高而下降,电阻温度系数在-2%/k~-6%/k范围内,约为金属电阻温度系数的10倍。NTC热敏电阻器电阻值的变化可以由外部环境温度的变化引起,也可以因有电流流过,自身发热而造成。它的各种用途都是基于这种特性。


NTC热敏电阻器由混合氧化物的多晶陶瓷构成。其导电机理是较为复杂的。


将NTC温度模块与A/D数据检测功能相配合,可实现温度的检测,它与开发板的连接如图1所示。
image.png

图1 实物连接


在连接时,所用的是图2中P14接口的PB0。
image.png

图2 所用接口


实现NTC温度检测的主程序为:


int main(void)
{
    uint32_t adc_result;
    uint32_t voltage;
    uint32_t V,u;
    sys_mpu_config();
    sys_cache_enable();
    HAL_Init();
    sys_stm32_clock_init(300, 6, 2);
    delay_init(600);
    led_init();
    hyperram_init();
    lcd_init();
    adc_init();
    lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
    lcd_show_string(30, 70, 200, 16, 16, "ADC TEST", RED);
    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH9_VAL: 0", BLUE);
    lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH9_VOL: 0.000V", BLUE);
    lcd_show_string(30, 150, 200, 16, 16, "NTC  (temp) :      C", BLUE);
    while (1)
    {
        adc_result = adc_get_result_average(ADC_ADCX_CHY, 20);
        lcd_show_xnum(142, 110, adc_result, 5, 16, 0, BLUE);
        voltage = (adc_result * VREFINT_CAL_VREF) / 4095;
        lcd_show_xnum(142, 130, voltage / 1000, 1, 16, 0, BLUE);
        lcd_show_xnum(158, 130, voltage % 1000, 3, 16, 0x80, BLUE);
        V=0;
        u=voltage;
         ...
        if((u<=1644) && (u>1268))
           V=10+(1644-u)/37;
        if((u<=1268) && (u>947))
           V=20+(1268-u)/32;
        if((u<=947) && (u>692))
           V=30+(947-u)/25;
        ...
        lcd_show_xnum(158, 150, V, 2, 16, 0x80, BLUE);
        LED0_TOGGLE();
        delay_ms(100);
    }
}

经程序的编译与下载,OLED屏的显示效果如图3和图4所示,即触摸NTC时其检测值可达30度左右,说明功能正常。
image.png

图3 触摸加热


image.png

图4 检测结构





回复

举报

jinglixixi 2024-12-17 13:43:22
15#

A/D检测数据的波形绘制:


使用STM32H7R3开发板所配置的TFT显示屏,不仅能显示文字信息,还能绘制波形曲线,所使用的关键函数就是lcd_draw_line()。


在NTC温度检测的基础上,可实现温度曲线的绘制功能,其主程序为:


int main(void)
{
    uint32_t adc_result;
    uint32_t voltage;
    uint32_t V,u;
    uint16_t x1,y1,x2,y2,n;
    sys_mpu_config();
    sys_cache_enable();
    HAL_Init();   
    sys_stm32_clock_init(300, 6, 2);
    delay_init(600);
    usart_init(115200);
    led_init();
    hyperram_init();
    lcd_init();
    adc_init();
    lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
    lcd_show_string(30, 70, 200, 16, 16, "ADC TEST", RED);
    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH9_VAL: 0", BLUE);
    lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH9_VOL: 0.000V", BLUE);
    lcd_show_string(30, 150, 200, 16, 16, "NTC  (temp) :      C", BLUE);
    lcd_draw_line(20, 300, 220, 300,RED);
    lcd_draw_line(20, 300, 20, 40,RED);               
    x1=20;
    y1=0;
    n=0;
    while (1)
    {
        adc_result = adc_get_result_average(ADC_ADCX_CHY, 20);
        lcd_show_xnum(142, 110, adc_result, 5, 16, 0, BLUE);
        voltage = (adc_result * VREFINT_CAL_VREF) / 4095;
        lcd_show_xnum(142, 130, voltage / 1000, 1, 16, 0, BLUE);
        lcd_show_xnum(158, 130, voltage % 1000, 3, 16, 0x80, BLUE);
        V=0;
        u=voltage;
        if((u<=1644) && (u>1268))
           V=10+(1644-u)/37;
        if((u<=1268) && (u>947))
           V=20+(1268-u)/32;
        if((u<=947) && (u>692))
           V=30+(947-u)/25;
        printf("temperature: %d C \\n", V);
        lcd_show_xnum(158, 150, V, 2, 16, 0x80, BLUE);
        LED0_TOGGLE();
        y2=V*5;
        if(y2>300)  y2=300;
        x2=x1+3;
        lcd_draw_line(x1, 300-y1, x2, 300-y2,RED);
        x1=x2;
        y1=y2;
        n=n+1;
        if(n>60)
        {
               x1=20;
               y1=0;
               n=0;               
               lcd_clear(WHITE);
               lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
               lcd_show_string(30, 70, 200, 16, 16, "ADC TEST", RED);
               lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
               lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH9_VAL: 0", BLUE);
               lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH9_VOL: 0.000V", BLUE);
               lcd_show_string(30, 150, 200, 16, 16, "NTC  (temp) :      C", BLUE);
               lcd_draw_line(20, 300, 220, 300,RED);
                lcd_draw_line(20, 300, 20, 40,RED);       
         }
         delay_ms(1000);
    }
}

在按图1连接电路的情况下,经程序的编译与下载,其检测效果如图2和图3所示。
image.png

图1 电路连接


image.png

图2 温度升降曲线


image.png

图3 温度下降曲线



回复

举报

jinglixixi 2024-12-18 15:34:27
16#

U盘读写测试:


U 盘,全称 USB 闪存盘,英文名“USB flash disk”。它是一种使用 USB 接口的无需物理驱动器的微型高容量移动存储产品,通过 USB 接口与主机连接,实现即插即用,是最常用的移动存储设备之一。


STM32H7R3开发板提供了U盘读写的测试功能,其电路如图1所示。
image.png

图1 U盘测试电路


U盘读写的测试主程序为:


int main(void)

{

    uint8_t t = 0;

    sys_mpu_config();

    sys_cache_enable();

    HAL_Init();

    sys_stm32_clock_init(300, 6, 2);

    delay_init(600);

    usart_init(115200);

led_init();

    hyperram_
init();

    lcd_init();

    usmart_dev.init(300);

    my_mem_init(SRAMIN);

    my_mem_init(SRAMEX);

my_mem_init(SRAM12);

my_mem_init(SRAMDTCM);

    my_mem_init(SRAMITCM);

    exfuns_init();

    f_mount(fs[0], "0:", 1);

    f_mount(fs[1], "1:", 1);

    f_mount(fs[2], "2:", 1);

    while (fonts_init() != 0)

    {

        lcd_show_string(30, 30, 200, 16, 16, "Font Error!  ", RED);

        delay_ms(500);

        lcd_show_string(30, 30, 200, 16, 16, "Please Check!", RED);

        delay_ms(500);

    }

    lcd_fill(30, 30, 30 + 200, 30 + 16, WHITE);

   

    text_show_string(30, 50, 200, 16, "STM32", 16, 0, RED);

    text_show_string(30, 70, 200, 16, "USB U盘(Host)实验", 16, 0, RED);

    text_show_string(30, 90, 200, 16, "ATOM@ALIENTEK", 16, 0, RED);

    text_show_string(30, 110, 200, 16, "等待U盘插入...", 16, 0, BLUE);

    USBH_Init(&g_usbh_handle, usbh_user_process, HOST_HS);

    USBH_RegisterClass(&g_usbh_handle, USBH_MSC_CLASS);

    USBH_Start(&g_usbh_handle);

    while (1)

    {

        USBH_Process(&g_usbh_handle);

        if (++t == 20)

        {

            t = 0;

            LED0_TOGGLE();

        }

        delay_ms(10);

    }

}

在连接U盘的情况下,如图2所示。经程序的编译与下载,其测试结果如图3所示。


image.png

图2 连接U盘


image.png

图3 测试结果


似乎到这里也就算结束了,然而且慢!


此时,若通过串口发送指令的话,还有新的收获。在发送指令“mf_scan_files("3:")”后,会扫描 U 盘,并显示根目录所有文件,见图4所示。若发送指令“mf_scan_files("3:/PICTURE")”,则会显示PICTURE 目录下的所有文件,见图5所示。


image.png

图4 显示根目录文件


image.png

图5 显示PICTURE 目录的文件


除了显示存在的文件外,使用指令还可以创建新文件并向其写入信息内容。


在发送指令“mf_open("3:test u disk.txt",7)”后,会在 U 盘根目录创建一个名为“test u disk.txt”的文件,见图6所示。然后若发送指令“mf_write("这是一个测试,写入文件",0x16)”,则会写入“这是一个测试,写入文件”到该文件,见图6所示。若关闭该文件,则发送指令“mf_close()”。


若想判别文件是否创建成功,可发送指令“mf_scan_files("3:")”,此时会发现已多出了一个名为“ test u disk.txt ”的文件,说明 U 盘写入成功,见图7所示。


image.png

图6 创建文件并写入内容


image.png

图7 测试 U 盘写入


后面会继续对该功能进行更升入的探索,因为这个功能非常重要且实用。



回复

举报

jinglixixi 2024-12-19 11:45:10
17#

U盘读写功能的实现探索:


前面介绍了U盘的测试,令人印象深刻的是可以通过串口以指令的方式来控制文件的读写。


那这一功能的实现基础是啥呢?


经追踪探索,原来它是通过调用usmart_config.c中的相关函数来实现的,这些函数有:


(void )mf_open, "uint8_t mf_open(uint8_tpath,uint8_t mode)",


(void *)mf_close, "uint8_t mf_close(void)",


(void *)mf_read, "uint8_t mf_read(uint16_t len)",


(void )mf_write, "uint8_t mf_write(uint8_tdat,uint16_t len)",


(void *)mf_scan_files, "uint8_t mf_scan_files(uint8_t * path)",


这样我们就清除如何在程序中直接来使用这些功能了,这些函数的内容如下:


扫描 U 盘目录文件函数:


uint8_t mf_scan_files(uint8_t *path)
{
    FRESULT res;
    res = f_opendir(&fattester.dir, (const TCHAR *)path);
    if (res == FR_OK)
    {
       printf("\\r\\n");
       while (1)
        {
           res = f_readdir(&fattester.dir, &fattester.fileinfo);
           if (res != FR_OK || fattester.fileinfo.fname[0] == 0)
           {
               break;
           }
           printf("%s/", path);
           printf("%s\\r\\n", fattester.fileinfo.fname);
       }
   }
    return res;
}

使用示例为:

mf_scan_files("3:");



mf_scan_files("3:/PICTURE");



打开文件函数:


uint8_t mf_open(uint8_t *path, uint8_t mode)
{
    uint8_t res;
    res = f_open(fattester.file, (const TCHAR *)path, mode);
    return res;
}

使用示例为:

mf_open("3:test u disk.txt",7);


关闭文件函数:


uint8_t mf_close(void)
{
    f_close(fattester.file);
    return 0;
}

使用示例为:

mf_close();


读取文件函数:


uint8_t mf_read(uint16_t len)
{
    uint16_t i, t;
    uint8_t res = 0;
    uint16_t tlen = 0;
    uint32_t br = 0;
    printf("\\r\\nRead fattester.file data is:\\r\\n");
    for (i = 0; i < len / 512; i++)
    {
        res = f_read(fattester.file, fattester.fatbuf, 512, &br);
        if (res)
        {
            printf("Read Error:%d\\r\\n", res);
            break;
        }
        else
        {
            tlen += br;
            for (t = 0; t < br; t++)printf("%c", fattester.fatbuf[t]);
        }
    }
    if (len % 512)
    {
        res = f_read(fattester.file, fattester.fatbuf, len % 512, &br);
        if (res)
        {
            printf("\\r\\nRead Error:%d\\r\\n", res);
        }
        else
        {
            tlen += br;
            for (t = 0; t < br; t++)printf("%c", fattester.fatbuf[t]);
        }
    }
    if (tlen)printf("\\r\\nReaded data len:%d\\r\\n", tlen);
    printf("Read data over\\r\\n");
    return res;
}

使用示例为:

pdata=mf_read(22);


文件写入函数:


uint8_t mf_write(uint8_t *pdata, uint16_t len)
{
    uint8_t res;
    uint32_t bw = 0;
    printf("\\r\\nBegin Write fattester.file...\\r\\n");
    printf("Write data len:%d\\r\\n", len);
    res = f_write(fattester.file, pdata, len, &bw);
    if (res)
    {
        printf("Write Error:%d\\r\\n", res);
    }
    else
    {
        printf("Writed data len:%d\\r\\n", bw);
    }
    printf("Write data over.\\r\\n");
    return res;
}

使用示例为:

mf_write("这是一个测试,写入文件",0x16);    // 0x16=22


弄清这些知识,在后面的绣花机仿真设计中就可以直接查询U盘中是否存在花板文件及提取花板文件的数据,以便控制步进电机定位移动或在显示屏上绘制出修制的效果。


回复

举报

jinglixixi 2024-12-19 19:49:10
18#

图片显示与数码相框:


图片的格式有很多种,但最常用的有不外乎这3种,即JPEG(或 JPG)、BMP 和 GIF。其中JPEG(或 JPG)和 BMP 是静态图片,而 GIF 则可实现动态图片。


(1)BMP 格式


它的全称 Bitmap,是 Window 操作系统中的标准图像文件格式,文件后缀名为“.bmp”,使用范围非常广泛。它采用的是位映射式的存储格式,除图像深度可选以外,未采用其他的压缩,因此,BMP文件所占用的空间很大,但是它不存在失真。


BMP 文件的图像深度可选1bit、4bit、8bit、16bit、24bit 及 32bit,BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。


(2)JPEG格式


它是 Joint Photographic Experts Group(联合图像专家组)的缩写,文件后辍名为“.jpg”或“.jpeg”,是最常用的图像文件格式,是由一个软件开发联合会组织所制定。同 BMP 格式不同,JPEG 是一种有损压缩格式,能将图像压缩在一个很小的储存空间,图像中重复或不重要的资料会被丢去,因而容易造成图像数据的损伤(BMP 不会,但是 BMP 占用空间大)。尤其是在使用过高压缩比例的情况下,将使最终解压缩后所恢复的图像质量明显降低。如果追求高品质图像,不宜采用过高压缩比例的方式。但是 JPEG 压缩技术很先进,它以有损压缩的方式去除了冗余的图像数据,在获得极高压缩率的同时,能展现十分丰富且生动的图像。换句话说,就是它可以用最少的磁盘空间得到较好的图像品质。此外,JPEG 也是一种很灵活的格式,具有调节图像质量的功能,允许用不同的压缩比对文件进行压缩,支持多种压缩级别,压缩比率通常在 10:1 到 40:1 之间,压缩比越大,品质就越低;相反地,压缩比越小,品质就越好。


(3)GIF


它是Graphics Interchange Format的缩写,是 CompuServe 公司开发的一种图像文件存储格式,1987 年开发的 GIF 文件格式版本号是 GIF87a,1989 年进行了扩充,扩充后的版本号定义为 GIF89a。


GIF 图像文件以数据块(block)为单位来存储图像的相关信息。一个 GIF 文件由表示图形/图像的数据块、数据子块以及显示图形/图像的控制信息块组成,称为 GIF 数据流(DataStream)。数据流中的所有控制信息块和数据块都必须在文件头(Header)和文件结束块(Trailer)之间。


GIF 文件格式采用了 LZW(Lempel-ZivWalch)压缩算法来存储图像数据,定义了允许用户为图像设置背景的透明(transparency)属性。此外,GIF 文件格式可在一个文件中存放多幅彩色图形/图像。如果在 GIF 文件中存放了多幅图,则它们可以像演幻灯片那样显示或者像动画那样演示。


STM32H7R3开发板所配置的图片显示主程序为:


int main(void)
{
    uint8_t t = 0;
    uint8_t key;
    uint8_t res;
    DIR picdir;
    uint16_t totpicnum;
    FILINFO *picfileinfo;
    char *pname;
    uint32_t *picoffsettbl;
    uint16_t curindex;
    uint16_t temp;
    sys_mpu_config();
    sys_cache_enable();
    HAL_Init();
    sys_stm32_clock_init(300, 6, 2);
    delay_init(600);
    usart_init(115200);
    led_init();
    key_init();
    hyperram_init();
    lcd_init();
    my_mem_init(SRAMIN);
    my_mem_init(SRAMEX);
    my_mem_init(SRAM12);
    my_mem_init(SRAMDTCM);
    my_mem_init(SRAMITCM);
    exfuns_init();
    f_mount(fs[0], "0:", 1);
    f_mount(fs[1], "1:", 1);
    f_mount(fs[2], "2:", 1);
    while (fonts_init() != 0)
    {
        lcd_show_string(30, 30, 200, 16, 16, "STM32", RED);
        while (sd_init() != 0)
        {
            lcd_show_string(30, 30, 200, 16, 16, "SD Card Error!", RED);
            delay_ms(500);
            lcd_show_string(30, 30, 200, 16, 16, "Please Check! ", RED);
            delay_ms(500);
            LED0_TOGGLE();
        }
        lcd_show_string(30, 50, 200, 16, 16, "SD Card OK", RED);
        lcd_show_string(30, 70, 200, 16, 16, "Font Updating...", RED);
        res = fonts_update_font(30, 90, 16, (uint8_t *)"0:", RED);
        while (res != 0)
        {
            lcd_show_string(30, 90, 200, 16, 16, "Font Update Failed!", RED);
            delay_ms(200);
            lcd_show_string(30, 90, 200, 16, 16, "Please Check!      ", RED);
            delay_ms(200);
        }
        lcd_show_string(30, 90, 200, 16, 16, "Font Update Success!   ", RED);
        delay_ms(1500);
        lcd_clear(WHITE);
    }
    text_show_string(30, 30, 200, 16, "正点原子STM32开发板", 16, 0, RED);
    text_show_string(30, 50, 200, 16, "图片显示实验", 16, 0, RED);
    text_show_string(30, 70, 200, 16, "ATOM@ALIENTEK", 16, 0, RED);
    text_show_string(30, 90, 200, 16, "WKUP: PREV", 16, 0, RED);
    text_show_string(30, 110, 200, 16, "KEY0: NEXT", 16, 0, RED);
    while (f_opendir(&picdir, "0:/PICTURE") != FR_OK)
    {
        text_show_string(30, 130, 200, 16, "PICTURE文件夹错误!", 16, 0, RED);
        delay_ms(200);
        lcd_fill(30, 130, 200, 16, WHITE);
        delay_ms(200);
    }
    totpicnum = pic_get_tnum("0:/PICTURE");
    while (totpicnum == 0)
    {
        text_show_string(30, 130, 200, 16, "没有图片文件!", 16, 0, RED);
        delay_ms(200);
        lcd_fill(30, 130, 200, 16, WHITE);
        delay_ms(200);
    }
    picfileinfo = (FILINFO *)mymalloc(SRAMIN, sizeof(FILINFO));
    pname = (char *)mymalloc(SRAMIN, FF_MAX_LFN * 2 + 1);
    picoffsettbl = (uint32_t *)mymalloc(SRAMIN, 4 * totpicnum);
    while ((picfileinfo == NULL) || (pname == NULL) || (picoffsettbl == NULL))
    {
        text_show_string(30, 130, 200, 16, "内存分配失败!", 16, 0, RED);
        delay_ms(200);
        lcd_fill(30, 130, 200, 16, WHITE);
        delay_ms(200);
    }
    res = (uint8_t)f_opendir(&picdir, "0:/PICTURE");
    if (res == 0)
    {
        curindex = 0;
        while (1)
        {
            temp = picdir.dptr;
            res = (uint8_t)f_readdir(&picdir, picfileinfo);
            if ((res != 0) || (picfileinfo->fname[0] == 0))
            {
                break;
            }
            
            res = exfuns_file_type(picfileinfo->fname);
            if ((res & 0xF0) == 0x50)
            {
                picoffsettbl[curindex] = temp;
                curindex++;
            }
        }
    }
    text_show_string(30, 130, 200, 16, "开始显示...", 16, 0, RED);
    delay_ms(1500);
    piclib_init();
    curindex = 0;
    res = (uint8_t)f_opendir(&picdir, (const TCHAR *)"0:/PICTURE");
    while (res == 0)
    {
        dir_sdi(&picdir, picoffsettbl[curindex]);
        res = (uint8_t)f_readdir(&picdir, picfileinfo);
        if ((res != 0) || (picfileinfo->fname[0] == 0))
        {
            break;
        }
        strcpy((char *)pname, "0:/PICTURE/");
        strcat((char *)pname, (const char *)picfileinfo->fname);
        lcd_clear(BLACK);
        piclib_ai_load_picfile(pname, 0, 0, lcddev.width, lcddev.height, 1);
        text_show_string(2, 2, lcddev.width, 16, (char *)pname, 16, 1, RED);
        while (1)
        {
            key = key_scan(0);
            if (key == KEY0_PRES)
            {
                if (curindex != 0)
                {
                    curindex--;
                }
                else
                {
                    curindex = totpicnum - 1;
                }
                break;
            }
            else if (key == WKUP_PRES)
            {
                curindex++;
                if (curindex >= totpicnum)
                {
                    curindex = 0;
                }
                break;
            }
            if (++t == 20)
            {
                t = 0;
                LED0_TOGGLE();
            }
            delay_ms(10);
        }
    }
    myfree(SRAMIN, picfileinfo);
    myfree(SRAMIN, pname);
    myfree(SRAMIN, picoffsettbl);
    while (1);
}

值得指出的是,该程序并不是一个单纯显示图片的程序,它是建立在基于U盘的文件管理系统之上,当把存有.bmp、.jpg及.gif这3种格式的图片文件的U盘插入开发板的卡槽后,它能在按键的配合下实现自主的浏览,即起到了数码相册的作用。


经程序的编译与下载,其显示效果如图1和图2所示。此外,可使用 WKUP 和 KEY0 键进行上一张或下一张图片的快速切换。


image.png


图1 显示bmp图片


image.png

图2 显示jpg图片


回复

举报

jinglixixi 2024-12-20 21:22:54
19#

音频播放与录制功能测试:


STM32H7R3 开发板配有串行音频接口(SAI),它具有灵活性高、配置多样的特点,适用于多声道或单声道应用。

SAI 接口的特点有:

(1)具有两个独立的音频子模块,子模块既可作为接收器,也可作为发送器,并自带 FIFO。

(2)每个音频子模块集成多达 8 个字,每个字 32 位的 FIFO。

(3)两个音频子模块间可以是同步或异步模式

(4)两个音频子模块的主/从配置相互独立

(5)当两个音频子模块都配置为主模式时,每个子模块可设置互相独立的采样率。

(6)数据大小可配置8 位、10 位、16 位、20 位、24 位或 32 位

(7)支持I2S、LSB 或 MSB 对齐、PCM/DSP、TDM 和 AC 97 等音频协议

(8)高达 16 个大小可配置的 Slot,可选择音频帧中的哪些 Slot 有效。

(9)支持 LSB 或 MSB 数据传输

(10)支持 DMA,有 2 个专业通道,用于处理每个 SAI 音频子模块的专用集成 FIFO 的访问。











SAI 的结构框图如图1 所示:
image.png

图1  结构框图


在开发板上是用 SAI 接口来驱动 ES8388,ES8388 是采用 I2S 接口,它最高 可支持192K 24BIT 的音频播放,并支持录音功能。

在音频播放和录音时,其使用的文件格式为WAV格式,它是计算机领域最常用的数字化声音文件格式之一,由微软专门为 Windows 系统定义的波形文件格式(Waveform Audio),由于其扩展名为"*.wav"而得名。它符合RIFF(Resource Interchange File Format)文件规范,用于保存 Windows 平台的音频信息资源,被Windows 平台及其应用程序所广泛支持,该格式也支持 MSADPCM,CCITT A LAW 等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的 WAV 文件和 CD 格式一样,也是 44.1K 的取样频率,16 位量化数字,因此在声音文件的质量上和 CD 相差无几!


音频播放的测试主程序为:


int main(void)
{
    sys_mpu_config();
    sys_cache_enable();
    HAL_Init();
    sys_stm32_clock_init(300, 6, 2);
    delay_init(600);
    usart_init(115200);
    led_init();
    key_init();
    hyperram_init();
    lcd_init();
    my_mem_init(SRAMIN);
    my_mem_init(SRAMEX);
    my_mem_init(SRAM12);
    my_mem_init(SRAMDTCM);
    my_mem_init(SRAMITCM);
    exfuns_init();
    f_mount(fs[0], "0:", 1);
    f_mount(fs[1], "1:", 1);
    f_mount(fs[2], "2:", 1);
    while (sd_init() != 0)
    {
        lcd_show_string(30, 30, 200, 16, 16, "SD Card Error!", RED);
        delay_ms(500);
        lcd_show_string(30, 30, 200, 16, 16, "Please Check! ", RED);
        delay_ms(500);
    }
    lcd_fill(30, 30, 30 + 200, 30 + 16, WHITE);
    while (fonts_init() != 0)
    {
        lcd_show_string(30, 30, 200, 16, 16, "Font Error!  ", RED);
        delay_ms(500);
        lcd_show_string(30, 30, 200, 16, 16, "Please Check!", RED);
        delay_ms(500);
    }
    lcd_fill(30, 30, 30 + 200, 30 + 16, WHITE);
    text_show_string(30, 50, 200, 16, "正点原子STM32开发板",16,0, RED);
    text_show_string(30, 70, 200, 16, "音乐播放器使用", 16, 0, RED);
    text_show_string(30, 90, 200, 16, "正点原子@ALIENTEK", 16, 0, RED);
    text_show_string(30, 110, 200, 16, "KEY0: Next", 16, 0, RED);
    text_show_string(30, 130, 200, 16, "KEY1: Prev", 16, 0, RED);
    text_show_string(30, 150, 200, 16, "KWY_UP: Play/Pause", 16, 0, RED);
    es8388_init();
    es8388_adda_cfg(1, 0);
   es8388_output_cfg(1, 1);
    es8388_hpvol_set(25);
    es8388_spkvol_set(25);
    while (1)
    {
        audio_play();
    }
}

在测试前,需把测试的WAV音频文件存入SD卡根目录下的MUSIC 文件夹内,并插入SD卡槽中。此外,为接听声音还需将耳机插入音频输出插孔,见图2所示。


image.png

图2 相关连接


经程序的编译与下载,在屏幕的显示内容有歌曲名字、播放时间、歌曲总时间、歌曲总数目、当前播放歌曲的编号等信息,如图3所示。

此外,使用KEY1 键可选取上一段内容,KEY0 键用于选择下一段内容,KEY_UP键则用来控制暂停/继续播放。


image.png

图3 显示内容


由于所设计的程序只支持WAV 文件,因此要播放MP3格式的歌曲,则需要进行文件的格式转换,见图4所示。


image.png

图4 格式转换软件


此外,使用音频录制功能也可以把电脑播放的MP3音乐转录为WAV格式文件,见图5所示。

后面会介绍一种以串口控制MP3功能模块来播放音乐的方法,它会更节省系统资源,并行性也会更高。


image.png

图5 音频录制与播放测试



回复

举报

只有小组成员才能发言,加入小组>>

12下一页

329个成员聚集在这个小组

加入小组

精选推荐

最新话题

热门话题

创建小组步骤

快速回复 返回顶部 返回列表
关注微信公众号

电子发烧友网

电子发烧友开云(中国)官方

社区合作
刘勇
联系电话:15994832713
邮箱地址:liuyong@huaqiu.com
社区管理
elecfans短短
微信:elecfans_666
邮箱:users@huaqiu.com
12下一页
关闭

站长推荐 上一条 /6 下一条

快速回复 返回顶部 返回列表
-

技术社区

张飞电子技术社区

KaihongOS技术社区

FPGA开发者技术社区

RISC-V MCU技术社区

HarmonyOS技术社区

-

OpenHarmony开源社区

OpenHarmony开源社区

-

嵌入式开云(中国)官方

ARM技术开云(中国)官方

STM32/STM8技术开云(中国)官方

嵌入式技术开云(中国)官方

单片机/MCU开云(中国)官方

RISC-V技术开云(中国)官方

瑞芯微Rockchip开发者社区

FPGA|CPLD|ASIC开云(中国)官方

DSP开云(中国)官方

-

电路图及DIY

电路设计开云(中国)官方

DIY及创意

电子元器件开云(中国)官方

专家问答

-

电源技术开云(中国)官方

电源技术开云(中国)官方

无线充电技术

-

综合技术与应用

机器人开云(中国)官方

USB开云(中国)官方

电机控制

模拟技术

音视频技术

综合技术交流

上位机软件(C/Python/Java等)

-

无线通信开云(中国)官方

WIFI技术

蓝牙技术

天线|RF射频|微波|雷达技术

-

EDA设计开云(中国)官方

PCB设计开云(中国)官方

DigiPCBA开云(中国)官方

Protel|AD|DXP开云(中国)官方

PADS技术开云(中国)官方

Allegro开云(中国)官方

multisim开云(中国)官方

proteus开云(中国)官方|仿真开云(中国)官方

KiCad EDA 中文开云(中国)官方

DFM|可制造性设计开云(中国)官方

-

测试测量开云(中国)官方

LabVIEW开云(中国)官方

Matlab开云(中国)官方

测试测量技术

传感技术

-

招聘/交友/外包/交易/杂谈

项目外包

供需及二手交易

工程师杂谈|交友

招聘|求职|工程师职场

-

官方社区

发烧友官方/活动

华秋商城

华秋电路