STM32大小端
STM32 是小端模式
例如假设 0x12345678
存放在内存的 0x100
位置
则 0x100
地址存放的是 0x78
, 0x03
地址存放的是 0x12
即低位存放在低地址,高位存放在高地址
address: 0x100 0x101 0x102 0x103
value: 0x78 0x56 0x34 0x12
强制转换为 char
后,读取出来是 0x78
例如假设 0x12345678
存放在内存的 0x100
位置
则 0x100
地址存放的是 0x78
, 0x03
地址存放的是 0x12
即低位存放在低地址,高位存放在高地址
address: 0x100 0x101 0x102 0x103
value: 0x78 0x56 0x34 0x12
强制转换为 char
后,读取出来是 0x78
一般OLED的分辨率为128 * 64,使用 uint64_t
貌似可以大幅度提高性能
原理:
STM32是小端模式,也就是个位存放在低地址
例如对于 uint64_t = 0x1122334455667788ULL
在内存中的位置为:
0x11 0x22 0x33 ... 0x88
[0x00] [0x01] [0x02] ... [0x07]
把OLED的刷屏方向改成按列刷新
COL0 COL1 ......... COL127
PAGE0 [0x00] [0x08] ......... [0x0388]
PAGE1 [0x01] [0x09] ......... [0x0389]
................................
PAGE6 [0x06] [0x0E] ......... [0x038E]
PAGE7 [0x07] [0x0F] ......... [0x038F]
测试一下,代码如下:
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint64_t a[2] = {
0x0011223344556677ULL,
0x8899AABBCCDDEEFFULL,
};
uint8_t* b = (uint8_t*)a;
for (int i = 0; i < 16; i++) {
printf("%d: 0x%02X\r\n", i, b[i]);
}
return 0;
}
运行结果:(这是在Windows里跑的,Windows也是小端)
0: 0x77
1: 0x66
2: 0x55
3: 0x44
4: 0x33
5: 0x22
6: 0x11
7: 0x00
8: 0xFF
9: 0xEE
10: 0xDD
11: 0xCC
12: 0xBB
13: 0xAA
14: 0x99
15: 0x88
--------------------------------
Process exited after 0.02992 seconds with return value 0 (0 ms cpu time, 2904 KB mem used).
Press ANY key to exit...
OLED 一般使用全屏缓冲区
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
// uint8_t buf[OLED_WIDTH * OLED_HEIGHT / 8];
uint64_t buf[OLED_WIDTH];
#define MASK_SET(x, mask) buf[x] |= (mask);
#define MASK_CLR(x, mask) buf[x] &= ~ (mask);
/* 需要检测x,y在合理的范围内 */
void oled_draw_pixel(int x, int y, int col) {
if (x < 0 || x >= OLED_WIDTH || y < 0 || y >= OLED_HEIGHT) {
return;
}
if (col) {
MASK_SET(x, 1ULL << y); // ULL: 64位
} else {
MASK_CLR(x, 1ULL << y);
}
}
void oled_set_pixel(int x, int y) {
MASK_SET(x, 1ULL << y);
}
void oled_clr_pixel(int x, int y) {
MASK_CLR(x, 1ULL << y);
}
int oled_get_pixel(int x, int y) {
return (buf[x] >> y) & 0x01;
}
/* 超高性能 */
void oled_vline(int x, int y, int h, int col) {
uint64_t mask = ((1ULL << h) - 1ULL) << y;
if (col) {
MASK_SET(x, mask);
} else {
MASK_CLR(x, mask);
}
}
/* 也很快 */
void oled_hline(int x, int y, int w, int col) {
uint64_t mask = 1ULL << y;
if (col) {
while (w--) {
MASK_SET(x++, 1ULL << y);
};
} else {
while (w--) {
MASK_CLR(x++, 1ULL << y);
};
}
}
void oled_rect(int x, int y, int w, int h, int col) {
oled_vline(x, y, h, col);
oled_vline(x + w - 1, y, h, col);
oled_hline(x + 1, y, w - 2, col);
oled_hline(x + 1, y + h - 1, w - 2, col);
}
void draw_circle(int x0, int y0, int r, int col) {
int x = r;
int y = 0;
int err = 0;
while (x >= y) {
// 画圆上的8个对称点
set_pixel(x0 + x, y0 + y, col);
set_pixel(x0 + y, y0 + x, col);
set_pixel(x0 - y, y0 + x, col);
set_pixel(x0 - x, y0 + y, col);
set_pixel(x0 - x, y0 - y, col);
set_pixel(x0 - y, y0 - x, col);
set_pixel(x0 + y, y0 - x, col);
set_pixel(x0 + x, y0 - y, col);
// 更新y和误差
y += 1;
if (err <= 0) {
err += 2 * y + 1;
}
// 更新x和误差
if (err > 0) {
x -= 1;
err -= 2 * x + 1;
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#define SIZE 4
int board[SIZE][SIZE];
// 初始化棋盘
void initializeBoard() {
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
board[i][j] = 0;
}
}
// 在棋盘上随机生成两个数字2或4
addRandomTile();
addRandomTile();
}
// 在棋盘上随机生成一个数字2或4
void addRandomTile() {
int value = (rand() % 2 + 1) * 2; // 生成2或4
int x, y;
do {
x = rand() % SIZE;
y = rand() % SIZE;
} while (board[x][y] != 0); // 找到一个空的位置
board[x][y] = value;
}
// 打印棋盘
void printBoard() {
printf("-----------------------------\n");
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
printf("| %4d ", board[i][j]);
}
printf("|\n");
printf("-----------------------------\n");
}
}
// 判断棋盘是否已满
bool isBoardFull() {
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (board[i][j] == 0) {
return false;
}
}
}
return true;
}
// 判断游戏是否结束
bool isGameOver() {
if (!isBoardFull()) {
return false;
}
// 检查是否有相邻的相同数字
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (i < SIZE - 1 && board[i][j] == board[i + 1][j]) {
return false;
}
if (j < SIZE - 1 && board[i][j] == board[i][j + 1]) {
return false;
}
}
}
return true;
}
// 向左移动
void moveLeft() {
for (int i = 0; i < SIZE; i++) {
int lastMerged = -1;
for (int j = 1; j < SIZE; j++) {
if (board[i][j] != 0) {
int k = j;
while (k > 0 && board[i][k - 1] == 0) {
board[i][k - 1] = board[i][k];
board[i][k] = 0;
k--;
}
if (k > 0 && board[i][k - 1] == board[i][k] && lastMerged != k - 1) {
board[i][k - 1] *= 2;
board[i][k] = 0;
lastMerged = k - 1;
}
}
}
}
}
// 向右移动
void moveRight() {
for (int i = 0; i < SIZE; i++) {
int lastMerged = SIZE;
for (int j = SIZE - 2; j >= 0; j--) {
if (board[i][j] != 0) {
int k = j;
while (k < SIZE - 1 && board[i][k + 1] == 0) {
board[i][k + 1] = board[i][k];
board[i][k] = 0;
k++;
}
if (k < SIZE - 1 && board[i][k + 1] == board[i][k] && lastMerged != k + 1) {
board[i][k + 1] *= 2;
board[i][k] = 0;
lastMerged = k + 1;
}
}
}
}
}
// 向上移动
void moveUp() {
for (int j = 0; j < SIZE; j++) {
int lastMerged = -1;
for (int i = 1; i < SIZE; i++) {
if (board[i][j] != 0) {
int k = i;
while (k > 0 && board[k - 1][j] == 0) {
board[k - 1][j] = board[k][j];
board[k][j] = 0;
k--;
}
if (k > 0 && board[k - 1][j] == board[k][j] && lastMerged != k - 1) {
board[k - 1][j] *= 2;
board[k][j] = 0;
lastMerged = k - 1;
}
}
}
}
}
// 向下移动
void moveDown() {
for (int j = 0; j < SIZE; j++) {
int lastMerged = SIZE;
for (int i = SIZE - 2; i >= 0; i--) {
if (board[i][j] != 0) {
int k = i;
while (k < SIZE - 1 && board[k + 1][j] == 0) {
board[k + 1][j] = board[k][j];
board[k][j] = 0;
k++;
}
if (k < SIZE - 1 && board[k + 1][j] == board[k][j] && lastMerged != k + 1) {
board[k + 1][j] *= 2;
board[k][j] = 0;
lastMerged = k + 1;
}
}
}
}
}
// 主函数
int main() {
srand(time(NULL));
initializeBoard();
printBoard();
char move;
while (true) {
printf("Enter move (w/a/s/d): ");
scanf(" %c", &move);
switch (move) {
case 'a': // 向左移动
moveLeft();
break;
case 'd': // 向右移动
moveRight();
break;
case 'w': // 向上移动
moveUp();
break;
case 's': // 向下移动
moveDown();
break;
default:
printf("Invalid move!\n");
continue;
}
if (!isBoardFull()) {
addRandomTile();
}
printBoard();
if (isGameOver()) {
printf("Game Over!\n");
break;
}
}
return 0;
}
/* 覆盖了内置的fputc函数,printf函数会调用fputc输出 */
int fputc(int ch, FILE* f) {
while ((USART1->ISR & 0x40) == 0);
USART1->TDR = (uint8_t) ch;
return ch;
}
#include <stdarg.h>
#include <stdio.h>
uint8_t uart2_tx_buf[200];
void uart2_printf(const char *format, ...) {
uint16_t len;
va_list args;
va_start(args, format);
len = vsnprintf((char*)uart2_tx_buf, sizeof(uart2_tx_buf)+1, (char*)format, args); // 为什么要 +1 ?
va_end(args);
HAL_UART_Transmit(&huart2, UartTxBuf, len, HAL_MAX_DELAY);
}