433 单引脚电平型程序
发射端 — EV1527 编码发送(单向遥控/报警)
发射端通过翻转 DATA 引脚(PA4)输出 OOK 信号,使用 EV1527 协议:前导码 + 同步码 + 20位地址 + 4位数据。
delay_us 基于 8MHz 系统时钟手动 NOP 校准,时间单位 T ≈ 4µs。
发送前关中断(GIE=0),发送后恢复,防止时序被打断。
// ---- 引脚 & 地址定义 ----
#define DATAOUT_HIGH PA4 = 1
#define DATAOUT_LOW PA4 = 0
#define g_my_addr 0x12345 // 20位地址,按需修改
#define is_leaking 0x02 // 4位数据:漏水状态
#define duima 0x01 // 4位数据:配对码
typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
typedef unsigned long uint32_t;
// 延时(基于 8MHz,每循环约 1us)
void delay_us(uint16_t us) {
uint16_t j;
us = us * 3;
for (j = 0; j < us; j++) {
NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();
}
}
// 前导码:10个脉冲,HIGH ~4us + LOW ~20us(AGC 锁定用)
void coding_preamble_1527(void) {
uint8_t i;
for (i = 0; i < 10; i++) {
DATAOUT_HIGH; delay_us(4);
DATAOUT_LOW; delay_us(20);
}
}
// 同步码:HIGH 4us + LOW 124us
void coding_syn_1527(void) {
DATAOUT_HIGH; delay_us(4);
DATAOUT_LOW; delay_us(124);
}
// 逻辑0:HIGH 4us + LOW 12us
void coding_L_1527(void) {
DATAOUT_HIGH; delay_us(4);
DATAOUT_LOW; delay_us(12);
}
// 逻辑1:HIGH 12us + LOW 4us
void coding_H_1527(void) {
DATAOUT_HIGH; delay_us(12);
DATAOUT_LOW; delay_us(4);
}
// 发送一帧:前导码 + 同步码 + 20位地址 + 4位数据
// addr: 20位地址(≤0xFFFFF),data: 4位数据(≤0xF)
void coding_1527(uint32_t addr, uint8_t data) {
uint8_t i, k;
uint32_t j;
if (addr > 0xFFFFF || data > 15) return;
GIE = 0;
coding_syn_1527();
for (i = 0; i < 20; i++) {
j = 0x80000 & addr;
addr <<= 1;
if (j) coding_H_1527(); else coding_L_1527();
}
for (i = 0; i < 4; i++) {
k = 0x08 & data;
data <<= 1;
if (k) coding_H_1527(); else coding_L_1527();
}
DATAOUT_HIGH; delay_us(4);
DATAOUT_LOW;
GIE = 1;
}
// 使用示例:发送漏水报警(发3次保可靠性)
void send_alarm(void) {
uint8_t i;
for (i = 0; i < 3; i++) {
coding_preamble_1527();
coding_1527(g_my_addr, is_leaking);
}
}接收端 — EV1527 解码(TIM1 90us 中断采样)
接收端用 TIM1 产生 90us 定时中断,在 ISR 中采样 PB7 引脚电平,统计高/低脉宽计数,
按 EV1527 协议识别前导码→同步码→24位数据(20位地址+4位数据)。
解码成功后写入 rf_data[3],置 rf_data_ready = 1,主循环轮询读取。
TIM1 时钟源为 HIRC = 32MHz(非系统时钟),ARR = 2879 → 90us。
// ---- rf433.h ----
typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
extern volatile uint8_t rf_data[3]; // 解码结果:[地址高][地址低][数据]
extern volatile uint8_t rf_data_ready; // 1=有新数据,主循环读完后清零
void RF433_Init(void); // 初始化 TIM1(90us 中断)
void RF433_ISR(void); // 放在 TIM1 更新中断 ISR 里调用
// ---- rf433.c ----
__at(0x20) static unsigned char flag;
#define bit_rf_ok (flag & 0x01)
#define bit_last_state (flag & 0x02)
#define bit_syn (flag & 0x04)
#define SET_rf_ok() (flag |= 0x01)
#define CLR_rf_ok() (flag &= ~0x01)
#define SET_last_high() (flag |= 0x02)
#define CLR_last_high() (flag &= ~0x02)
#define SET_syn() (flag |= 0x04)
#define CLR_syn() (flag &= ~0x04)
__at(0x21) static unsigned char a_code1;
__at(0x22) static unsigned char a_code2;
__at(0x23) static unsigned char a_code3;
__at(0x24) static unsigned char hh_w; // 高电平计数(单位:90us)
__at(0x25) static unsigned char ll_w; // 低电平计数
__at(0x26) static unsigned char t_code1;
__at(0x27) static unsigned char t_code2;
__at(0x28) static unsigned char t_code3;
__at(0x29) static unsigned char ma_x; // 当前解码位索引
__at(0x2A) static unsigned char pre_cnt;
#define PRE_CNT_MIN 5 // 至少5个前导码脉冲才接受同步码
static unsigned int s;
volatile unsigned char rf_data[3] = {0};
volatile unsigned char rf_data_ready = 0;
void RF433_Init(void) {
flag = 0; hh_w = 0; ll_w = 0;
t_code1 = 0; t_code2 = 0; t_code3 = 0;
ma_x = 0; s = 0; pre_cnt = 0;
// TIM1: HIRC=32MHz, ARR=2879 → 90us 中断
PCKEN |= 0x02; // 使能 TIM1 时钟
CKOCON = 0x20;
TCKSRC = 0x03; // 时钟源 HIRC=32MHz
TIM1CR1 = 0x84; // 自动预装载,向上计数,暂不使能
TIM1SR1 = 0;
TIM1IER = 0x01; // 使能更新中断
T1UIE = 1;
TIM1ARRH = 0x0B; // ARR = 2879 (0x0B3F)
TIM1ARRL = 0x3F;
TIM1CR1 = 0x85; // 使能计数器
GIE = 1;
}
static void set_bit(unsigned char bit_idx) {
unsigned char mask = (unsigned char)(0x80 >> (bit_idx & 0x07));
if (bit_idx < 8) t_code1 |= mask;
else if (bit_idx < 16) t_code2 |= (unsigned char)(0x80 >> ((bit_idx - 8) & 0x07));
else t_code3 |= (unsigned char)(0x80 >> ((bit_idx - 16) & 0x07));
}
static void save_code(void) {
a_code1 = t_code1; a_code2 = t_code2; a_code3 = t_code3;
SET_rf_ok(); CLR_syn(); s = 1000;
}
void RF433_ISR(void) {
if (PB7 == 0) {
ll_w++;
CLR_last_high();
} else {
hh_w++;
if (!(bit_last_state)) {
// 上升沿:处理上一个低电平脉宽
if ((hh_w >= 2 && hh_w <= 5) && (ll_w >= 15 && ll_w <= 25)) {
// 前导码
if (pre_cnt < 255) pre_cnt++;
} else if ((pre_cnt >= PRE_CNT_MIN) &&
(hh_w >= 2 && hh_w <= 5) && (ll_w >= 80 && ll_w <= 165)) {
// 同步码
SET_syn(); pre_cnt = 0; ma_x = 0;
t_code1 = 0; t_code2 = 0; t_code3 = 0;
} else if ((bit_syn) && (ll_w >= 7 && ll_w <= 13)) {
// 逻辑0
ma_x++;
if (ma_x > 23 && !bit_rf_ok) save_code();
} else if ((bit_syn) && (ll_w >= 2 && ll_w <= 7)) {
// 逻辑1
if (ma_x <= 23) {
set_bit(ma_x);
if (ma_x == 23 && !bit_rf_ok) save_code();
ma_x++;
}
} else {
// 干扰,重置
pre_cnt = 0; ma_x = 0; CLR_syn();
t_code1 = 0; t_code2 = 0; t_code3 = 0; ll_w = 0;
}
ll_w = 0; hh_w = 1;
}
SET_last_high();
}
if (bit_rf_ok) {
s--;
if (!s) CLR_rf_ok();
rf_data[0] = a_code1;
rf_data[1] = a_code2;
rf_data[2] = a_code3;
rf_data_ready = 1;
}
T1UIF = 1; // 清中断标志(写1清零)
}
// ---- 主循环中读取示例 ----
// if (rf_data_ready) {
// rf_data_ready = 0;
// // rf_data[0..2] 即 24位解码结果(高位在前)
// // 地址 = (rf_data[0]<<12) | (rf_data[1]<<4) | (rf_data[2]>>4)
// // 数据 = rf_data[2] & 0x0F
// }