USART

发送数据

while (usart_flag_get(USART1, USART_TDBE_FLAG) == 0);  // 等待发送缓冲区为空
usart_data_transmit(USART1, ch); // 往发送缓冲区里放入一个字节(然后自动发送)

引脚定义

2025-03-21T17:37:46.png
2025-03-21T17:38:18.png

寄存器地址

2025-03-21T17:39:21.png
00H ~ 05H 三轴地磁数据,小端模式
DRDY 新数据标识 1有新数据
OVL 溢出标志 寄存器的数值超过 int16_t 范围
TOUT 相对温度,每℃约变化100

电路图

2025-03-21T17:36:00.png

|-----|-----|-----|
|  1  |  3  |  5  |
|-----|-----|-----|
|  8  |  7  |  2  |
|-----|-----|-----|
|  6  |  4  |     |
|-----|-----|-----|

大概是这样一个 3*3 的棋盘,去掉右下角然后打乱,通过上下左右移动使之拼成正确的顺序

uint8_t board[COLS * ROWS] = { 0 };

/* 找到那个空位 */
uint32_t find_blank(void) {
    for (int i = 0; i < COLS * ROWS; i++) {
        if (board[i] == 0) {
            break;
        }
    }
    return i;
}

void init_board(void) {
    /* 顺序填充面板,最后一个空着 */
    for (int i = 0; i < COLS * ROWS - 1; i++) {
        board[i] = i + 1;
    }

    /* Fisher-Yates 洗牌算法 */
    for (int i = COLS * ROWS - 1; i > 0; i--) {
        int j = rand() % (i + 1);
        int temp = board[i];
        board[i] = board[j];
        board[j] = temp;
    }
}

void move_up(void) {
    uint32_t i = find_blank();
    if (i < COLS * (ROWS - 1)) {
        board[i] = board[i + COLS];
        board[i + COLS] = 0;
        return 1;
    }
    return 0;
}

void move_down(void) {
    uint32_t i = find_blank();
    if (i >= ROWS) {
        board[i] = board[i - COLS];
        board[i - COLS] = 0;
        return 1;
    }
    return 0;
}

void move_left(void) {
    uint32_t i = find_blank();
    if (i % COLS < COLS - 1) {
        board[i] = board[i + 1];
        board[i + 1] = 0;
        return 1;
    }
    return 0;
}

void move_right(void) {
    uint32_t i = find_blank();
    if (i % COLS > 0) {
        board[i] = board[i - 1];
        board[i - 1] = 0;
        return 1;
    }
    return 0;
}

判断游戏结束

这个游戏只有胜利才是结束条件

int is_success(void) {
    for (int i = 0; i < COLS * ROWS - 1; i++) { // 最后一个单元格不算
        if (board[i] != i + 1) {
            return 0;
        }
    }
    return 1;
}

R1是下电阻,接 FB - GND
R2是上电阻,接 VOUT - FB
R3接 DAC - FB

2025-03-12T01:58:17.png

#include <stdio.h>
#include <stdint.h>

float r1 = 10, r2 = 56, r3 = 12;
float vfb = 1.25;

float calc_vout(float vdac) {
    return (1 + r2 / r1 + r2 / r3) * vfb - r2 / r3 * vdac;
}

int main(void) {
    printf("R1 %.02f R, R1 %.02f R, R1 %.02f R, Vfb %.02f V\r\n", r1, r2, r3, vfb);
    for (float i = 0; i <= 3.3; i += 0.3) {
        printf("VDAC %.02f V; VOUT %.02f V\r\n", i, calc_vout(i));
    }
    return 0;
}

打印结果如下,可实现0-12V可调电源:

R1 10.00 R, R1 56.00 R, R1 12.00 R, Vfb 1.25 V
VDAC 0.00 V; VOUT 14.08 V
VDAC 0.30 V; VOUT 12.68 V
VDAC 0.60 V; VOUT 11.28 V
VDAC 0.90 V; VOUT 9.88 V
VDAC 1.20 V; VOUT 8.48 V
VDAC 1.50 V; VOUT 7.08 V
VDAC 1.80 V; VOUT 5.68 V
VDAC 2.10 V; VOUT 4.28 V
VDAC 2.40 V; VOUT 2.88 V
VDAC 2.70 V; VOUT 1.48 V
VDAC 3.00 V; VOUT 0.08 V
VDAC 3.30 V; VOUT -1.32 V

推导过程:

I1 = Vfb / R1
I2 = Vout - Vfb / R2
I3 = Vdac - Vfb / R3  # 电流方向可正可负,此处定义 Vdac -> Vfb 为正
I1 = I2 + I3

==> Vout = (1 + R2 / R1 + R2 / R3) * Vfb - R2 / R3 * Vdac

STM32 是小端模式

例如假设 0x12345678 存放在内存的 0x100 位置
0x100 地址存放的是 0x78, 0x03 地址存放的是 0x12
即低位存放在低地址,高位存放在高地址

address:  0x100  0x101  0x102  0x103
value:    0x78   0x56   0x34   0x12

强制转换为 char 后,读取出来是 0x78