![]() |
發布時間: 2017-6-16 09:53
正文摘要:本人菜鳥,前段時間按網友推薦用CD4017做了一個4路音頻輸入切換控制板(下圖),發現掉電時不能鎖定掉電前的那一路,每次通電總是默認接通第一路,后加紐扣記憶電池雖然可以實現記憶了,但耗電很快,不到5天時間工作 ... |
wulin 發表于 2017-7-1 09:58 照著搭了個電路試了下。手動切換是可以的。但是貌似EEPROM沒能寫成功。斷電后重新上電不是斷電前的狀態。 |
wulin 發表于 2017-7-1 09:58 感謝您的無私奉獻,回頭我試試。 |
jimi123 發表于 2017-6-30 15:13 給你寫了程序和電路圖: ![]() #include "STC15W104.H" //單片機頭文件 //#include "STC15F104.H" //單片機頭文件 #include <intrins.h> //庫頭文件 #define uint unsigned int //宏定義數據類型uint #define uchar unsigned char //宏定義數據類型uchar /**宏定義ISP的操作命令****/ #define CMD_IDLE 0 //空閑模式 #define CMD_READ 1 //IAP字節讀命令 #define CMD_PROGRAM 2 //IAP字節編程命令 #define CMD_ERASE 3 //IAP扇區擦除命令 #define ENABLE_IAP 0x82 //CPU的等待時間 #define IAP_ADDRESS 0x0400 //測試地址 /********端口定義*********/ sbit OUT1=P3^0; //輸出端口定義 sbit OUT2=P3^1; sbit OUT3=P3^2; sbit OUT4=P3^3; sbit CN =P3^4; //備用端口定義 sbit key =P3^5; //按鍵端口定義 /*******變量聲明**********/ uchar ch; //中間變量 uint tim; //鍵值變量 bit flag=0; //操作標志 /******子程序聲明*********/ void keyscan(); //按鍵識別子程序聲明 void key_service(); //按鍵服務程序聲明 void Preservation(); //寫入狀態數據 /****EEPROM操作程序聲明****/ void IapIdle(); //關閉IAP/EEPROM uchar IapReadByte(uint addr); //讀取EEPROM數據 void IapProgramByte(uint addr, uchar dat);//寫入EEPROM數據 void IapEraseSector(uint addr); //擦除EEPROM數據 /*******主函數*************/ void main() { P3M1 = 0x00; //設置P3.0~P3.3推挽模式:0000 0000 P3M0 = 0x0f; //設置P3.0~P3.3推挽模式:0000 1111 tim=IapReadByte(IAP_ADDRESS); //程序開始時讀取EEPROM中數據 if((tim<1)||(tim>4)) //判斷讀取的鍵值數據是否有效 { tim=0; //鍵值數據無效即清0 } while(1) { keyscan(); //按鍵識別程序 key_service(); //按鍵服務程序 Preservation(); //保存鍵值程序 P1=ch; //輸出狀態 } } /*********按鍵識別子程序**********/ void keyscan() { static bit key_sign=0; //按鍵自鎖標志 static uchar count=0; //消抖計數變量 if(key==0) //檢測按鍵如果為0 { count++; //消抖計數 if(count>=100) //100次檢測按鍵如果為0 { count=100; //防止溢出 if(key_sign==0) //按鍵自鎖標志為0 { key_sign=1; //按鍵自鎖標志置1 flag=1; //操作標志置1 tim++; //狀態變量自+1 if(tim>4) //如果tim>4 tim=0; //tim>4清0 } } } else { key_sign=0; //按鍵自鎖標志清0 count=0; //消抖計數清0 } } /*********按鍵服務程序**********/ void key_service() { switch(tim) { case 0: ch=0xf0; //備用端輸出高電平 break; case 1: ch=0xe1; //第1通道輸出高電平 break; case 2: ch=0xe2; //第2通道輸出高電平 break; case 3: ch=0xe4; //第3通道輸出高電平 break; case 4: ch=0xe8; //第4通道輸出高電平 break; } } /*********保存鍵值數據程序**********/ void Preservation() { if(flag==1) //如果操作標志為1 { flag=0; //操作標志清0 IapEraseSector(IAP_ADDRESS);//擦除EEPROM數據 IapProgramByte(IAP_ADDRESS,tim);//寫入EEPROM數據 } } /**********關閉IAP功能************/ void IapIdle() { IAP_CONTR = 0; //關閉IAP功能 IAP_CMD = 0; //清除命令寄存器 IAP_TRIG = 0; //清除觸發寄存器 IAP_ADDRH = 0x80; //將地址設置到非IAP區域 IAP_ADDRL = 0; } /***從ISP/IAP/EEPROM區域讀取一字節***/ uchar IapReadByte(uint addr) { uchar dat; //數據緩沖區 IAP_CONTR = ENABLE_IAP; //使能IAP IAP_CMD = CMD_READ; //設置IAP命令 IAP_ADDRL = addr; //設置IAP低地址 IAP_ADDRH = addr >> 8; //設置IAP高地址 IAP_TRIG = 0x5a; //寫觸發命令(0x5a) IAP_TRIG = 0xa5; //寫觸發命令(0xa5) _nop_(); //等待ISP/IAP/EEPROM操作完成 dat = IAP_DATA; //讀ISP/IAP/EEPROM數據 IapIdle(); //關閉IAP功能 return dat; //返回數據 } /***寫一字節數據到ISP/IAP/EEPROM區域***/ void IapProgramByte(uint addr, uchar dat) { IAP_CONTR = ENABLE_IAP; //使能IAP IAP_CMD = CMD_PROGRAM; //設置IAP命令 IAP_ADDRL = addr; //設置IAP低地址 IAP_ADDRH = addr >> 8; //設置IAP高地址 IAP_DATA = dat; //寫ISP/IAP/EEPROM數據 IAP_TRIG = 0x5a; //寫觸發命令(0x5a) IAP_TRIG = 0xa5; //寫觸發命令(0xa5) _nop_(); //等待ISP/IAP/EEPROM操作完成 IapIdle(); //關閉IAP功能 } /***ISP/IAP/EEPROM扇區擦除****/ void IapEraseSector(uint addr) { IAP_CONTR = ENABLE_IAP; //使能IAP IAP_CMD = CMD_ERASE; //設置IAP命令 IAP_ADDRL = addr; //設置IAP低地址 IAP_ADDRH = addr >> 8; //設置IAP高地址 IAP_TRIG = 0x5a; //寫觸發命令(0x5a) IAP_TRIG = 0xa5; //寫觸發命令(0xa5) _nop_(); //等待ISP/IAP/EEPROM操作完成 IapIdle(); //關閉IAP功能 } ![]() |
wulin 發表于 2017-6-25 08:59 我想用STC15F104,能否給具體的電路和程序 ![]() |
1.采用內含EEPROM的單片機,把操作數據保存,下次開機讀取保存的操作數據控制相應電路,如STC15F104等 2.AT89C2051+外接EEPROM,把操作數據保存,下次開機讀取保存的操作數據控制相應電路,如AT24CXX系列 3.使用充電電池,只單獨給4017保持供電,4017靜態電流不到1mA,4個晶體管換為MOS管,以降低4017電耗 |
1.采用內含EEPROM的單片機,把操作數據保存,下次開機讀取保存的操作數據控制相應電路,如STC15F104等 2.AT89C2051+外接EEPROM,把操作數據保存,下次開機讀取保存的操作數據控制相應電路,如AT24CXX系列 3.使用充電電池,只單獨給4017保持供電,4017靜態電流不到1mA,4個晶體管換為MOS管,以降低4017電耗 |
cjjcjj1 發表于 2017-6-16 12:29 沒關系的,互相學習嘛 |