- 打卡等级:初来乍到
- 打卡总天数:3
- 最近打卡:2026-03-05 19:49:18
已绑定手机
新手上路
- 积分
- 11
|
请教各位大神一下 STC8G1K08单片机为何在读取AD时会经常读取到0 使用的AD0 也设置了高祖输入 AD口也加了滤波 测试时就发现两路AD都会读取到0 后来就改成单独测试1个AD口 因为我的程序设置的是当温度高于xx度后 继电器动作 我下好程序放在哪经常听见继电器动作 然后我就把程序修改成了先AD转换温度 后串口发送 我就看到 经常性的 有时候20 30秒 有时候1分钟 温度数据就从 20-20-20-160-20-20就这样猛的一下160度 下一秒又20度 他这个漂移不是那种20-21-23-20-21 不是这种在附近漂移的是突然猛地一下就160 我这个是负温度系数的 也就是单片机读取到了0 才转换成了160度 温度采集的还好说可以程序滤波一下 主要是我程序稳定了后还有个高速的AD采集 我希望是滤波之前采集到的AD差不多的数据 别突然是0 之前用的是stc15w408as没有出过这种问题 最近用stc8g1k08就一直没搞好 有没有大神给看下哪里原因
#include "STC8G.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define SAMPLE_COUNT 16 // 0.2秒内采样16次(12.5ms间隔)
#define REMOVE_COUNT 4 // 去除4个最高和4个最低值
uint code adc_table[]={
994 ,// -40 0
992 ,// -39 1
990 ,// -38 2
988 ,// -37 3
985 ,// -36 4
983 ,// -35 5
980 ,// -34 6
977 ,// -33 7
974 ,// -32 8
971 ,// -31 9
968 ,// -30 10
964 ,// -29 11
961 ,// -28 12
957 ,// -27 13
953 ,// -26 14
949 ,// -25 15
945 ,// -24 16
940 ,// -23 17
936 ,// -22 18
931 ,// -21 19
926 ,// -20 20
921 ,// -19 21
915 ,// -18 22
910 ,// -17 23
904 ,// -16 24
898 ,// -15 25
892 ,// -14 26
885 ,// -13 27
878 ,// -12 28
872 ,// -11 29
864 ,// -10 30
857 ,// -9 31
850 ,// -8 32
842 ,// -7 33
834 ,// -6 34
826 ,// -5 35
817 ,// -4 36
809 ,// -3 37
800 ,// -2 38
791 ,// -1 39
782 ,// 0 40
772 ,// 1 41
763 ,// 2 42
753 ,// 3 43
743 ,// 4 44
733 ,// 5 45
722 ,// 6 46
712 ,// 7 47
701 ,// 8 48
691 ,// 9 49
680 ,// 10 50
669 ,// 11 51
658 ,// 12 52
647 ,// 13 53
636 ,// 14 54
624 ,// 15 55
613 ,// 16 56
602 ,// 17 57
590 ,// 18 58
579 ,// 19 59
568 ,// 20 60
556 ,// 21 61
545 ,// 22 62
534 ,// 23 63
522 ,// 24 64
512 ,// 25 65
500 ,// 26 66
489 ,// 27 67
478 ,// 28 68
467 ,// 29 69
456 ,// 30 70
445 ,// 31 71
435 ,// 32 72
424 ,// 33 73
414 ,// 34 74
404 ,// 35 75
394 ,// 36 76
384 ,// 37 77
374 ,// 38 78
364 ,// 39 79
355 ,// 40 80
346 ,// 41 81
337 ,// 42 82
328 ,// 43 83
319 ,// 44 84
310 ,// 45 85
302 ,// 46 86
294 ,// 47 87
286 ,// 48 88
278 ,// 49 89
270 ,// 50 90
263 ,// 51 91
255 ,// 52 92
248 ,// 53 93
241 ,// 54 94
234 ,// 55 95
228 ,// 56 96
221 ,// 57 97
215 ,// 58 98
209 ,// 59 99
203 ,// 60 100
197 ,// 61 101
191 ,// 62 102
186 ,// 63 103
181 ,// 64 104
176 ,// 65 105
170 ,// 66 106
166 ,// 67 107
161 ,// 68 108
156 ,// 69 109
152 ,// 70 110
147 ,// 71 111
143 ,// 72 112
139 ,// 73 113
135 ,// 74 114
131 ,// 75 115
127 ,// 76 116
124 ,// 77 117
120 ,// 78 118
117 ,// 79 119
114 ,// 80 120
110 ,// 81 121
107 ,// 82 122
104 ,// 83 123
101 ,// 84 124
98 ,// 85 125
96 ,// 86 126
93 ,// 87 127
90 ,// 88 128
88 ,// 89 129
85 ,// 90 130
83 ,// 91 131
81 ,// 92 132
79 ,// 93 133
76 ,// 94 134
74 ,// 95 135
72 ,// 96 136
70 ,// 97 137
68 ,// 98 138
67 ,// 99 139
65 ,// 100 140
63 ,// 101 141
61 ,// 102 142
60 ,// 103 143
58 ,// 104 144
57 ,// 105 145
55 ,// 106 146
54 ,// 107 147
52 ,// 108 148
51 ,// 109 149
50 ,// 110 150
48 ,// 111 151
47 ,// 112 152
46 ,// 113 153
45 ,// 114 154
44 ,// 115 155
43 ,// 116 156
41 ,// 117 157
40 ,// 118 158
39 ,// 119 159
38 ,// 120 160
37 ,// 121 161
37 ,// 122 162
36 ,// 123 163
35 ,// 124 164
34 ,// 125 165
33 ,// 126 166
32 ,// 127 167
32 ,// 128 168
31 ,// 129 169
30 ,// 130 170
29 ,// 131 171
29 ,// 132 172
28 ,// 133 173
27 ,// 134 174
27 ,// 135 175
26 ,// 136 176
25 ,// 137 177
25 ,// 138 178
24 ,// 139 179
24 ,// 140 180
23 ,// 141 181
23 ,// 142 182
22 ,// 143 183
22 ,// 144 184
21 ,// 145 185
21 ,// 146 186
20 ,// 147 187
20 ,// 148 188
19 ,// 149 189
19 ,// 150 190
18 ,// 151 191
18 ,// 152 192
18 ,// 153 193
17 ,// 154 194
17 ,// 155 195
17 ,// 156 196
16 ,// 157 197
16 ,// 158 198
16 ,// 159 199
15 ,// 160 200
};
sbit k1 = P5^4; // LED1也是继电器引脚
sbit keyhx = P3^6; // 换向
bit hx,js = 0, dqsc_bite = 0, xr = 0;
void Timer0_Init();
void InitUart();
void SendData(uchar dat);
void Delay(uint n);
void InitADC();
void sendNbyte(unsigned char * pmsg,unsigned int plen);
int Temp_Cal( uint adc );
void kzbf();//自动控制部分
void xieru();//寄存器写入
void IapIdle(); //关闭IAP
uchar read_add(uint addr); //读EEPROM
void write_add(uint addr,uchar ch); //直接写EEPROM
void Sector_Erase(uint addr); //扇区擦除
void system_start();//初始化
int wd,szwd;
uchar ch; //ADC通道号
unsigned int szjgsj,szscsj,dqscsj,dqjgsj; //int类型0到65535
unsigned char szjgsjh,szjgsjl,szscsjh,szscsjl,szwdh,szwdl,jsz,cnt,jsms,kzms,shoudong;//char类型0到255
uint AD_10dat;
unsigned char buf_reg=0;
unsigned char recivebuff[10];
unsigned char recive_cnt=0,start_flag=0;
bit ad_over_bit,sys_tt, hx_bite = 0;
unsigned int AD_TEMP;
idata unsigned char sbuff2[21];
// 使用IDATA存储大数组(内部间接寻址RAM,256字节空间)
static idata unsigned int adc_buf[SAMPLE_COUNT]; // 采样数据缓冲区,32字节
// ----------------------------
// 主函数
// ----------------------------
void main()
{
// GPIO 模式初始化(推挽/高阻,根据你的硬件需求)
P1M0 = 0x00; P1M1 = 0x01;
P3M0 = 0x00; P3M1 = 0x00;
P5M0 = 0x10; P5M1 = 0x00;
wd=-40;
k1 =0;
system_start();
Timer0_Init(); // 50ms 定时器中断
InitUart(); // 初始化串口(UART1,定时器1做波特率)
InitADC(); // 初始化ADC
IE = 0xB2; // 使能 ADC 中断
EA = 1; // 开总中断
while (1)
{
if (sys_tt == 1)
{
// unsigned int i; // 外层循环变量
// unsigned int j; // 内层循环变量
// unsigned int swap; // 交换变量
// unsigned long sum; // 求和变量
uchar high_byte;
uchar low_byte;
unsigned char a;
unsigned char checksum = 0;
sys_tt=0;
// // ========== 冒泡排序(从小到大) ==========
// // 对最近16次采样进行排序
// for(i = 0; i < SAMPLE_COUNT-1; i++)
// {
// for(j = i+1; j < SAMPLE_COUNT; j++)
// {
// if(adc_buf[i] > adc_buf[j])
// {
// swap = adc_buf[i];
// adc_buf[i] = adc_buf[j];
// adc_buf[j] = swap;
// }
// }
// }
// // ========== 排序结束 ==========
//
// // ========== 去极值求平均 ==========
// // 去除最大的4个值(索引12-15)和最小的4个值(索引0-3)
// // 取中间8个值(索引4-11)求平均值
// sum = 0;
// for(i = REMOVE_COUNT; i < SAMPLE_COUNT - REMOVE_COUNT; i++)
// {
// sum += adc_buf[i]; // 累加中间8个值
// }
// AD_TEMP = sum / 8; // 计算平均值(16-4-4=8个值)
// // ========== 滤波完成 ==========
// // 数据范围校验
// if(AD_TEMP > 1023)
// {
// AD_TEMP = 1023;
// }
//
wd=Temp_Cal( AD_TEMP );
high_byte = (wd >> 8) & 0xFF;
low_byte = wd & 0xFF;
sbuff2[0] = 0xab;
sbuff2[1] = 0xcd;
sbuff2[2] = 0x01;
sbuff2[3] = szwd / 256;
sbuff2[4] = szwd % 256;
sbuff2[5] = high_byte;
sbuff2[6] = low_byte;
sbuff2[7] = szscsj / 256;
sbuff2[8] = szscsj % 256;
sbuff2[9] = dqscsj / 256;
sbuff2[10] = dqscsj % 256;
sbuff2[11] = szjgsj / 256;
sbuff2[12] = szjgsj % 256;
sbuff2[13] = dqjgsj / 256;
sbuff2[14] = dqjgsj % 256;
sbuff2[15] = kzms;
sbuff2[16] = jsms;
sbuff2[17] = k1;
// sbuff2[17] = keyhx;
for (a = 2; a < 18; a++)
checksum += sbuff2[a];
checksum &= 0xFF;
sbuff2[18] = checksum;
sbuff2[19] = 0xdc;
sbuff2[20] = 0xba;
sendNbyte(sbuff2, 21);
}
kzbf(); // 你的功能函数
if (xr == 1)
{
xr = 0;
xieru(); // 你的写入函数
}
if (ad_over_bit == 1)
{
ad_over_bit = 0; // 清除ADC完成标志
}
}
}
/*----------------------------
控制部分
----------------------------*/
void kzbf(void)
{
if(dqsc_bite==1) //如果当前的状态是输出状态
{
//输出计时--
if(dqscsj==0) //如果输出计时到了0
{
k1=0; //将继电器关闭
dqsc_bite=0; //复位输出模式
dqjgsj=szjgsj; //取读取值 赋值给等待时间
}
else k1=1;
}
else // 当前的模式是等待间隔时间
{
if(dqjgsj==0) //如果等待间隔时间到达0
{
if((kzms==1&&jsms==1)||(kzms==0&&wd>=szwd )) //如果控制模式是1(计时模式)需要当前为计时自动模式 或 //如果控制模式是0(控温模式) 需要当前的温度大于设置温度
{ if(wd>=szwd)sys_tt = 1;
dqsc_bite=1; //置位输出模式
dqscsj=szscsj; //取内存数据 赋值给输出时间
k1=1; //打开继电器
}
}
else k1=0;
}
if ((shoudong==1)||(hx==1&&hx_bite==0))
{
if(hx==1)hx_bite=1;
shoudong=0; //复位手动状态
k1=1; //打开继电器
dqsc_bite=1; //置位输出模式
dqjgsj=0; //清除等待时间
dqscsj=szscsj; //取内存数据 赋值给输出时间
}
if (shoudong==2)
{
shoudong=0; //复位手动状态
k1=0; //关闭继电器
dqsc_bite=0; //复位输出模式
dqjgsj=szjgsj; //取内存数据 赋值给输出时间
dqscsj=0; //清除输出时间
}
if(hx==0&&hx_bite==1)//如果按键松开 且按过一次 并且没有暂停输出状态
{
hx_bite=0;
}
if(dqjgsj>szjgsj) dqjgsj=szjgsj;
if(dqscsj>szscsj) dqscsj=szscsj;
}
// ----------------------------
// 定时器0 中断(5ms)
// ----------------------------
void Timer0_Isr(void) interrupt 1
{
static unsigned char keybuf = 0xff;//按键扫描缓冲区
TH0 = 0xEE; // 5ms @11.0592MHz,定时器0,模式1,12T(请确认是否准确)
TL0 = 0x00;
cnt++;
jsz++;
if (jsz >= 50)//串口发送的间隔时间
{
jsz = 0;
sys_tt = 1;
}
if (cnt >= 200)//每隔一秒钟执行一次倒计时
{
cnt = 0;
if(dqsc_bite==1&&dqscsj>0) dqscsj--; //输出时间--
else if(dqsc_bite==0&&dqjgsj>0)dqjgsj--; //等待间隔时间--
}
keybuf = (keybuf<<1) | keyhx;//缓冲区左移一位并把当前扫描值保存到最后一位
if(keybuf==0xff)//如果八次扫描值都为1,那么认为按键是按下状态
hx=1;
else if(keybuf == 0x00) { // 连续8次都是低电平
hx = 0; // 按键松开
}
}
void system_start()
{
szwdh=read_add(0x0200);
szwdl=read_add(0x0201);
szscsjh=read_add(0x0202);
szscsjl=read_add(0x0203);
szjgsjh=read_add(0x0204);
szjgsjl=read_add(0x0205);
kzms=read_add(0x0230);
jsms=read_add(0x0231);
szjgsj=(szjgsjh<<8)|szjgsjl;
szscsj=(szscsjh<<8)|szscsjl;
szwd=(szwdh<<8)|szwdl;
if( (szwd>160) || (szwd<=0) ||
(szscsj>65000) || (szscsj==0) ||
(szjgsj>65000) || (szjgsj==0) ||
(kzms>1) || (jsms>1) )
{
szwd=90;
szscsj=6;
szjgsj=120;
kzms=0;
jsms=0;
xieru();
}
if(kzms==1&&jsms==1)
{
dqsc_bite=1;
dqscsj=szscsj;
}
else dqsc_bite=0;
}
// ----------------------------
// 定时器0 初始化(5ms)
// ----------------------------
void Timer0_Init(void)
{
TMOD &= 0xF0; // 清除定时器0模式位
TMOD |= 0x01; // 定时器0,模式1(16位定时器)
TH0 = 0xEE; // 请根据你的晶振和实际定时需求确认是否为5ms
TL0 = 0x00;
TF0 = 0;
TR0 = 1; // 启动定时器0
ET0 = 1; // 允许中断
}
// ----------------------------
// 发送一个字节
// ----------------------------
void SendData(unsigned char dat)
{
SBUF = dat;
while (!TI);
TI = 0;
}
// ----------------------------
// 发送N字节
// ----------------------------
void sendNbyte(unsigned char *pmsg, unsigned int plen)
{
unsigned int i;
for (i = 0; i < plen; i++)
SendData(pmsg[i]);
}
// ----------------------------
// ADC 中断服务程序
// ----------------------------
void adc_isr() interrupt 5 using 1
{
ADC_CONTR &= ~0x20; // 清除ADC中断标志(STC8G可能是 0x10,请根据手册确认)
ad_over_bit = 1;
// 读取ADC转换结果
AD_10dat = ADC_RES & 0xFF; // 获取高8位
AD_10dat = (AD_10dat << 2) | (ADC_RESL & 0x03); // 拼接低2位
// 存储采样值到缓冲区(持续采样,不断更新)
AD_TEMP = AD_10dat;
AD_10dat = 0; // 清零临时变量
ADC_CONTR |= 0x40; // 启动下一次ADC转换
}
// ----------------------------
// 初始化ADC(使用P5.5,通道5)
// ----------------------------
void InitADC(void)
{ P1M1 |= (1 << 0); // P1.0高阻输入模式
P1M0 &= ~(1 << 0); // 确保P1.0为模拟输入
// ADC_CONTR = 0x8d; // 使能ADC电源|低速模式|选择通道5
// // 0x80: ADC电源使能
// // 0x05: 通道5选择
//
// ADCCFG = 0x0F; // 配置ADC时钟和结果格式
// // bit7-6: 00-结果右对齐
// // bit5-4: 11-ADC时钟=Fosc/16
// // bit3-0: 1111-保留
//
// Delay(3); // 等待ADC电源稳定(至少1ms)
// ADC_CONTR |= 0x40; //启动AD转换
P_SW2 |= 0x80;
ADCTIM = 0x3f; //设置ADC内部时序
P_SW2 &= 0x7f;
ADCCFG = 0x0f; //设置ADC时钟为系统时钟/2/16
ADC_CONTR = 0x80; //使能ADC模块
EADC = 1; //使能ADC中断
Delay(3); // 等待ADC电源稳定(至少1ms)
ADC_CONTR |= 0x40; //启动AD转换
}
// ----------------------------
// 串口初始化(UART1,使用定时器1做波特率)
// ----------------------------
void InitUart(void)
{
// 切换串口引脚到P1.6/P1.7(TXD_3/RXD_3)
P_SW1 |= 0x80; // 设置P_SW1.6=1,选择P3.2/P3.3作为串口引脚
// 2. 配置P1.6(RXD)为高阻输入
P1M0 &= ~(1 << 6); // P1M0.6 = 0
P1M1 |= (1 << 6); // P1M1.6 = 1 → 高阻输入模式
// 3. 配置P1.7(TXD)为推挽输出
P1M0 |= (1 << 7); // P1M0.7 = 1
P1M1 &= ~(1 << 7); // P1M1.7 = 0 → 推挽输出模式
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE0; //设置定时初始值
TH1 = 0xFE; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
ES = 1; // 允许串口中断
}
/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4 using 1 {
if (RI) {
RI = 0; // 清除接收中断标志
buf_reg = SBUF; // 读取接收到的数据
// 如果接收到起始标志 0xEF,并且未开始接收数据帧
if (buf_reg == 0xEF && start_flag == 0) {
recive_cnt = 0; // 重置接收计数器
start_flag = 1; // 开始接收数据帧
}
// 检查 recive_cnt 是否超出缓冲区大小
if (recive_cnt < sizeof(recivebuff)) {
recivebuff[recive_cnt] = buf_reg; // 将数据存入缓冲区
recive_cnt++;
} else {
// 缓冲区已满,丢弃数据并重置接收状态
recive_cnt = 0;
start_flag = 0;
}
// 检查是否接收到完整的数据帧
if (buf_reg == 0xFE && recive_cnt == 6 && start_flag == 1) {
// 数据帧格式:0xEF | 地址 | 数据1 | 数据2 | 校验和 | 0xFE
unsigned char address = recivebuff[1];
unsigned char data1 = recivebuff[2];
unsigned char data2 = recivebuff[3];
unsigned char received_checksum = recivebuff[4];
// 计算校验和
unsigned char calculated_checksum = (address + data1 + data2) & 0xFF;
// 校验通过
if (calculated_checksum == received_checksum) {
// 处理接收到的数据
if (address == 0x00) { // 设置温度
uint linshi = data1 * 256 + data2; // 声明 linshi
if (linshi <= 160 && linshi > 0) {
szwd = linshi;
xr = 1;
}
}
if (address == 0x01) { // 设置反吹时间
uint linshi = data1 * 256 + data2; // 声明 linshi
if (linshi <= 65000 && linshi > 0) {
szscsj = linshi;
xr = 1;
}
}
if (address == 0x02) { // 设置间隔时间
uint linshi = data1 * 256 + data2; // 声明 linshi
if (linshi <= 65000 && linshi > 0) {
szjgsj = linshi;
xr = 1;
}
}
if (address == 0x03) { // 设置工作模式
unsigned char linshia = data2; // 声明 linshia
if (linshia <= 1) {
kzms = linshia;
xr = 1;
}
}
if (address == 0x04) { // 设置计时模式
unsigned char linshia = data2; // 声明 linshia
if (linshia <= 1) {
jsms = linshia;
xr = 1;
}
}
if (address == 0x05) { // 手动开关
unsigned char linshia = data2; // 声明 linshia
if (linshia <= 2) {
if (k1 == 1) {
cnt=0;
shoudong = 2;
} else {
cnt=0;
shoudong = 1;
}
}
}
}
// 重置接收状态
recive_cnt = 0;
start_flag = 0;
}
}
}
// ----------------------------
// 延时函数
// ----------------------------
void Delay(uint n)
{
uint x;
while (n--)
{
x = 5000;
while (x--);
}
}
// ----------------------------
// 温度计算函数(需用户提供 adc_table[])
// ----------------------------
int Temp_Cal(uint adc) {
int low = 0, high = 200;
if (adc > adc_table[0]) {
return -40; // 如果ADC值小于最小值,返回最低温度
}
if (adc < adc_table[200]) {
return 160; // 如果ADC值大于最大值,返回最高温度
}
while (low <= high) {
int mid = (low + high) / 2;
if (adc >= adc_table[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return (low - 1) - 40;
}
void xieru()//寄存器写入
{
szscsjl = szscsj&0XFF;//低八位
szscsjh = szscsj>>8;//高八位
szjgsjl = szjgsj&0XFF;//低八位
szjgsjh = szjgsj>>8;//高八位
szwdl = szwd&0XFF;//低八位
szwdh = szwd>>8;//高八位
Sector_Erase(0x200);
write_add(0x0200,szwdh);
write_add(0x0201,szwdl);
write_add(0x0202,szscsjh);
write_add(0x0203,szscsjl);
write_add(0x0204,szjgsjh);
write_add(0x0205,szjgsjl);
write_add(0x0230,kzms);
write_add(0x0231,jsms);
szwdh=read_add(0x0200);
szwdl=read_add(0x0201);
szscsjh=read_add(0x0202);
szscsjl=read_add(0x0203);
szjgsjh=read_add(0x0204);
szjgsjl=read_add(0x0205);
kzms=read_add(0x0230);
jsms=read_add(0x0231);
szjgsj=(szjgsjh<<8)|szjgsjl;
szscsj=(szscsjh<<8)|szscsjl;
szwd=(szwdh<<8)|szwdl;
}
void IapIdle() //关闭IAP
{
IAP_CONTR = 0; //关闭IAP功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非IAP区域
IAP_ADDRL = 0;
}
//读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节
uchar read_add(uint addr) //读EEPROM
{
char dat;
EA = 0;
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 12; //设置等待参数12MHz
IAP_CMD = 1; //设置IAP读命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();
dat = IAP_DATA; //读IAP数据
IapIdle(); //关闭IAP功能
EA = 1;
return dat;
}
//字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据
void write_add(uint addr,uchar dat) //直接写EEPROM
{
EA = 0;
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 12; //设置等待参数12MHz
IAP_CMD = 2; //设置IAP写命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_DATA = dat; //写IAP数据
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();
IapIdle(); //关闭IAP功能
EA = 1;
}
//擦除扇区, 入口:DPTR = 扇区地址
void Sector_Erase(uint addr) //扇区擦除
{
EA = 0;
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 12; //设置等待参数12MHz
IAP_CMD = 3; //设置IAP擦除命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //
IapIdle(); //关闭IAP功能
EA = 1;
}
|
-
原理图
-
pcb图
|