SuperAPI AI Directory

pw-embedded-c-style

Coding & development

View repository

Updated 10-15 21:47

About this skill

pw-embedded-c-style

Embedded C code style assistant, based on a code style analysis of 302 .c files and 66 .h files from "Hands-On Learning of 51 Microcontrollers".

Default naming style: snake_case

Use cases

Applicable situations

  • Creating new embedded C projects (51 microcontrollers, STM32, etc.)
  • Optimizing the naming and structure of existing embedded code
  • Generating hardware driver modules (timers, serial ports, LCD, buttons, etc.)
  • Standardizing project file organization and code style
  • Learning best practices for embedded C programming

Inapplicable situations

  • General-purpose non-embedded C/C++ projects
  • Projects that require an RTOS or a complex architecture
  • Pure algorithm implementations (no hardware interaction)

Usage

Default naming style: snake_case

If camelCase is needed, explicitly state "use camelCase" in the instruction.

Create project

# 基础示例 (默认蛇形命名)
/pw-embedded-c-style 创建一个 LED 闪烁的项目

# 带外设的项目
/pw-embedded-c-style 创建一个带 LCD1602 显示和按键输入的项目

# 指定芯片
/pw-embedded-c-style 为 STM32F103 创建一个串口通信项目

# 明确指定使用驼峰命名
/pw-embedded-c-style 使用驼峰命名创建一个定时器项目

Optimize code

# 优化代码风格 (默认蛇形命名)
/pw-embedded-c-style 帮我优化这段按键扫描代码

# 重构模块
/pw-embedded-c-style 将这段代码重构为独立的驱动模块

# 添加注释
/pw-embedded-c-style 为这段定时器配置代码添加规范注释

# 使用驼峰命名优化
/pw-embedded-c-style 使用驼峰命名优化这段代码

Generate driver template

# 生成特定外设驱动
/pw-embedded-c-style 生成 DS1302 实时时钟驱动模板

# 生成通信协议
/pw-embedded-c-style 生成串口通信的收发缓冲区实现

Core conventions

Naming conventions

Default style: snake_case

// 函数: 蛇形命名
void config_timer0(unsigned int ms);
void lcd_write_cmd(unsigned char cmd);
void init_ds1302(void);

// 变量: 蛇形命名
unsigned char flag_500ms = 0;
unsigned char cnt_rxd = 0;

// 宏/常量: 全大写下划线
#define SYS_MCLK    (11059200/12)
#define LCD1602_RS  P1^0

// sbit: 全大写或蛇形
sbit LED = P0^0;
sbit EN_LED = P1^4;

Alternative style: camelCase/PascalCase

Use this style when the user explicitly requests it:

// 函数: 大驼峰
void ConfigTimer0(unsigned int ms);
void LcdWriteCmd(unsigned char cmd);
void InitDS1302(void);

// 变量: 小驼峰
unsigned char flag500ms = 0;
unsigned char cntRxd = 0;

// 宏/常量: 全大写下划线 (相同)
#define SYS_MCLK    (11059200/12)
#define LCD1602_RS  P1^0

// sbit: 全大写或大驼峰
sbit LED = P0^0;
sbit ENLED = P1^4;

Code organization

Single-file project

#include <reg52.h>

// 宏定义
// sbit 定义
// 全局变量
// 函数声明

void main() { }
// 函数实现
// 中断函数

Multi-file project

config.h    - 全局配置 (类型定义、系统参数、IO 定义)
module.h    - 模块头文件 (结构体、extern 声明、函数声明)
module.c    - 模块实现 (#define _MODULE_C)
main.c      - 主程序

Common patterns

Timer configuration

void config_timer0(unsigned int ms)
{
    unsigned long tmp;
    tmp = 11059200 / 12;
    tmp = (tmp * ms) / 1000;
    tmp = 65536 - tmp;
    tmp = tmp + 12;
    T0RH = (unsigned char)(tmp>>8);
    T0RL = (unsigned char)tmp;
    TMOD &= 0xF0;
    TMOD |= 0x01;
    TH0 = T0RH;
    TL0 = T0RL;
    ET0 = 1;
    TR0 = 1;
}

Interrupt service routine

void interrupt_timer0() interrupt 1
{
    static unsigned char tmr_500ms = 0;
    TH0 = T0RH;
    TL0 = T0RL;
    if (++tmr_500ms >= 50)
    {
        tmr_500ms = 0;
        flag_500ms = 1;
    }
}

Flag-driven

bit flag_500ms = 0;

// 中断中设置
flag_500ms = 1;

// 主循环检测
while (1)
{
    if (flag_500ms)
    {
        flag_500ms = 0;
        // 执行任务
    }
}

Button debouncing

void key_scan(void)
{
    static unsigned char keybuf[4] = {0xFF, 0xFF, 0xFF, 0xFF};
    keybuf[i] = (keybuf[i] << 1) | KEY_IN[i];
    if ((keybuf[i] & 0x0F) == 0x00)
        key_sta[i] = 0;  // 稳定按下
}

Lookup table method

unsigned char code led_char[] = {
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
P0 = led_char[num];

Comment style

/* 文件头注释 */
/*
*******************************************************************************
* 文件名称: main.c
* 描  述: 功能描述
* 版本号: v1.0.0
*******************************************************************************
*/

/* 函数注释 */
void lcd_show_str(unsigned char x, unsigned char y,
                  unsigned char *str, unsigned char len)

// 行内注释
EA = 1;                     // 使能总中断
config_timer0(10);          // 配置 T0 定时 10ms

Code style characteristics

  • Concise and direct, avoid over-abstraction
  • Directly manipulate hardware registers
  • Use sbit to define IO ports
  • Specify interrupt vector numbers directly (interrupt 1)
  • Storage area modifiers (code, pdata)
  • Flag-driven main loop
  • Use lookup tables to handle data mapping

Best practices

Naming style selection

Use snake_case by default:

  • Matches the style of the Linux kernel and most open-source embedded projects
  • Word separation is obvious, readability is good
  • Suitable for production projects and team collaboration

Scenarios for using camelCase/PascalCase:

  • Teaching projects or reference textbooks use camelCase
  • The team explicitly requires the use of camelCase
  • Needs to remain consistent with existing camelCase code

Important principle: the entire project must use a unified naming style

Project creation recommendations

  1. Single-file project: suitable for simple functions (LED blinking, button detection, etc.)
  2. Multi-file project: suitable for coordination of multiple peripherals (LCD + buttons + serial port, etc.)
  3. Modular drivers: each peripheral is an independent .h/.c file pair

Code optimization recommendations

  1. Naming conventions: use snake_case by default (functions/variables), and use all-uppercase underscores for macros
  2. Interrupt minimization: interrupt functions only set flag bits, the main loop handles business logic
  3. Hardware abstraction: use macro definitions to isolate hardware-related code, facilitating portability
  4. Clear comments: key register configurations must have inline comments added

Common error handling

Problem 1: Inaccurate timer

// 错误: 未考虑指令周期补偿
tmp = 65536 - tmp;

// 正确: 加上补偿值
tmp = 65536 - tmp;
tmp = tmp + 12;  // 补偿中断响应延迟

Problem 2: Key debouncing

// 错误: 直接读取按键状态
if (KEY == 0) { /* 处理 */ }

// 正确: 使用移位寄存器消抖
keybuf = (keybuf << 1) | KEY;
if ((keybuf & 0x0F) == 0x00) { /* 稳定按下 */ }

Problem 3: Global variable conflicts

// 错误: 多个模块使用相同变量名
unsigned char flag;  // 在多个 .c 文件中定义

// 正确: 使用模块前缀或 static
static unsigned char uart_flag;  // 仅本文件可见
extern unsigned char g_system_flag;  // 全局共享

Precautions

  • Interrupt functions must return as soon as possible to avoid long occupation
  • When global variables are shared between interrupts and the main loop, use the volatile qualifier
  • Large arrays use the code modifier to be stored in ROM, saving RAM
  • Do not call delay functions in interrupts
  • Multi-file projects must use extern to correctly declare global variables

Technical parameter description

Supported chip platforms

  • 51 series: AT89C51, STC89C52, STC15, etc.
  • STM32 series: F103, F407, etc. (register definitions need adjustment)
  • Other 8051-compatible chips

Source of code standards

Based on the actual teaching project of "Teach You 51 Microcontroller Step by Step":

  • 302 .c source files
  • 66 .h header files
  • Covers 20+ common peripheral drivers
  • Snake case is used by default, which better conforms to embedded C project standards

Output format

  • Single-file project: generate main.c
  • Multi-file project: generate config.h, module.h, module.c, main.c
  • Driver module: generate driver.h, driver.c

Example scenarios

Scenario 1: Rapid prototype verification

User requirement: "Create a program where an LED blinks once per second"

Assistant output:

  • A single main.c file
  • Includes timer configuration and interrupt function
  • Uses flag bits to drive LED toggling

Scenario 2: Modular project

User requirement: "Create a project with LCD1602 displaying temperature and key adjustment"

Assistant output:

  • config.h (system configuration)
  • lcd1602.h/c (LCD driver)
  • key.h/c (key driver)
  • ds18b20.h/c (temperature sensor driver)
  • main.c (main program)

Scenario 3: Code optimization

User requirement: "Optimize this serial port receiving code"

Assistant operations:

  • Check naming conventions
  • Optimize buffer management
  • Add overflow protection
  • Supplement explanatory comments

Summarized based on actual teaching projects, focusing on practicality and readability. Snake case naming style is used by default, conforming to embedded C project standards.