|
- /*******************************************************************************
- 程序名稱:Keyer 自動鍵控制程序
- *******************************************************************************/
- #include <STC89C5xRC.H>
- #include <intrins.h>
- #include <stdlib.h>
- #include <config.h>
- /* 定義IO端口宏 */
- #define GPIO_DIG P0 //定義數(shù)碼管IO
- #define GPIO_KEY P1 //定義鍵盤IO
- /* 定義數(shù)碼管 */
- sbit LSA = P2^2;
- sbit LSB = P2^3;
- sbit LSC = P2^4;
- /* 定義IO端口 */
- sbit BEEP = P1^5; //定義蜂鳴器
- sbit CWOUT = P2^0; //定義電鍵信號發(fā)送端口與LED
- sbit K1 = P3^0; //定義K1鍵為功能鍵
- sbit K2 = P3^1; //定義K2鍵為播放鍵
- sbit K3 = P3^2; //定義Dot鍵使用外部中斷INT0
- sbit K4 = P3^3; //定義Dash鍵使用外部中斷INT1
- /* 聲明功能函數(shù) */
- void IntConfiguration(void); //中斷配置
- void Delay(uint t); //延時(shí)(t=毫秒數(shù))
- void TimeCount(void); //計(jì)算Dot/Dash時(shí)長
- void Paddle(void); //自控電碼發(fā)生
- void Straight(void); //手控電碼發(fā)生
- void Space(uchar n); //間隔發(fā)生器(n=間隔數(shù)目)
- void Function(void); //功能鍵控制
- void PlayCall(void); //發(fā)送本臺呼號
- void Display(void); //數(shù)碼管顯示
- void RecordInfor(void); //錄入本臺呼號
- void WriteSystem(void); //寫入系統(tǒng)參數(shù)
- void Player(uchar m, uchar x[]); //發(fā)送內(nèi)置信息(m=發(fā)送字符數(shù))
- /* 聲明ISP操作函數(shù) */
- void EEPROM_Read(uint EE_address, uchar *DataAddress, uchar n); //字節(jié)讀
- void EEPROM_Write(uint EE_address, uchar *DataAddress, uchar n); //字節(jié)寫
- void EEPROM_SectorErase(uint EE_address); //扇區(qū)擦除
- /* 數(shù)碼管顯示碼表,0 1 2 3 4 5 6 7 8 9 */
- const uchar code DIG_CODE[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
- /* 側(cè)音頻率表,400,500,600,700,800,900,1000Hz */
- const uchar code Tone_H[7] = {0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE};
- const uchar code Tone_L[7] = {0x1E, 0x18, 0xBF, 0x36, 0x8F, 0xD4, 0x0C};
- /* 呼叫數(shù)組 */
- const uchar code C1[10] = {'1','0','1','0','.','1','1','0','1',' '};
- const uchar code C2[6] = {'1','0','0','.','0',' '};
- const uchar code C3[14] = {'0','1','1','0','.','0','0','0','.','0',' ','1','0','1'};
- /* 定義變量 */
- uint DotTime, DashTime; //Dot時(shí)長,Dash時(shí)長
- uint TCount, Tmax; //時(shí)長計(jì)數(shù),時(shí)長閾值
- uchar KeyValue; //功能鍵值
- uchar Cmax = 54, CW_x[56]; //數(shù)組上標(biāo),錄入緩存
- uchar WPM = 16; //發(fā)報(bào)速度4-60wpm (默認(rèn)16wpm)
- uchar ToneFreq = 3; //側(cè)音頻率序號0-6 (默認(rèn)3/700Hz)
- uchar Number; //播發(fā)字符數(shù)
- bit KeyFlg = 1; //點(diǎn)劃交替標(biāo)志(1=無點(diǎn)劃交替)
- bit SendFlg = 0; //發(fā)送標(biāo)志(1=禁止發(fā)射)
- static uint T2Count = 0; //定時(shí)器T2計(jì)數(shù)變量
- void main(void)
- {
- /* 設(shè)定初始值 */
- IntConfiguration(); //配置中斷
- if (K1 == 0) //按K1鍵開機(jī)進(jìn)行系統(tǒng)重置
- {
- WPM = 16;
- ToneFreq = 3;
- Number = 0;
- WriteSystem();
- EEPROM_SectorErase(SectorAddr_2);
- }
- else
- {
- EEPROM_Read(SectorAddr_1, CW_x, 3); //讀系統(tǒng)設(shè)定參數(shù)
- if (CW_x[0] != 0xFF)
- {
- WPM = CW_x[0];
- ToneFreq = CW_x[1];
- Number = CW_x[2];
- }
- }
- TimeCount(); //計(jì)算Dot/Dash時(shí)長
- TH1 = Tone_H[ToneFreq]; //設(shè)定定時(shí)器T1(側(cè)音頻率)初始值
- TL1 = Tone_L[ToneFreq];
- TR2 = 1; //開定時(shí)器T2
- /* 運(yùn)行按鍵監(jiān)測程序 */
- while (1)
- {
- SendFlg = 0; //允許發(fā)射
- Display();
- Delay(15);
- if (K1 == 0) //功能鍵按下
- {
- Delay(1000);
- if (K1 == 0)
- Function();
- }
- if (K2 == 0 && Number > 0)
- PlayCall();
- }
- }
- /*******************************************************************************
- 函 數(shù) 名:IntConfiguration
- 函數(shù)功能:設(shè)置中斷參數(shù)
- *******************************************************************************/
- void IntConfiguration(void)
- {
- IT0 = 0; //INT0為低電平觸發(fā)方式
- IT1 = 0; //INT1為低電平觸發(fā)方式
- EX0 = 1; //INT0中斷允許
- EX1 = 1; //INT1中斷允許
- TMOD = 0x12; //定時(shí)器T0工作方式為2,定時(shí)器T1工作方式為1
- PT0 = 1; //定時(shí)器T0(時(shí)長)高優(yōu)先級
- PT1 = 1; //定時(shí)器T1(側(cè)音)高優(yōu)先級
- ET0 = 1; //定時(shí)器T0中斷允許
- ET1 = 1; //定時(shí)器T1中斷允許
- T2CON = 0x00; //定時(shí)器T2工作方式為16位自動重載定時(shí)器
- ET2 = 1; //定時(shí)器T2中斷允許
- TH0 = 0x9C; //設(shè)定定時(shí)器T0為100us
- TL0 = 0x9C;
- RCAP2H = 0x0B; //設(shè)定定時(shí)器T2為每秒中斷16次
- RCAP2L = 0xDC;
- EA = 1; //開總中斷
- }
- /*******************************************************************************
- 函 數(shù) 名:Int0
- 函數(shù)功能:外部中斷0觸發(fā)時(shí)發(fā)送Dot
- *******************************************************************************/
- void Int0(void) interrupt 0
- {
- Delay(5); //消抖
- if (K3 == 0)
- {
- if (KeyFlg == 1) //不是點(diǎn)劃交替發(fā)送Dot
- {SEND_DOT();}
- if (K4 == 0) //點(diǎn)劃交替發(fā)送Dash
- {
- SEND_DASH();
- KeyFlg = 1; //清除點(diǎn)劃交替標(biāo)志
- }
- }
- }
- /*******************************************************************************
- 函 數(shù) 名:Int1
- 函數(shù)功能:外部中斷1觸發(fā)時(shí)發(fā)送Dash
- *******************************************************************************/
- void Int1(void) interrupt 2
- {
- Delay(5); //消抖
- if (K4 == 0)
- {
- SEND_DASH();
- if (K3 == 0) //點(diǎn)劃交替發(fā)送Dot
- {
- SEND_DOT();
- KeyFlg = 0; //設(shè)置點(diǎn)劃交替標(biāo)志
- }
- }
- }
- /*******************************************************************************
- 函 數(shù) 名:Timer0
- 函數(shù)功能:定時(shí)器T0的中斷函數(shù),產(chǎn)生100us/次的延時(shí),控制發(fā)碼時(shí)長。
- *******************************************************************************/
- void Timer0(void) interrupt 1
- {
- TCount++;
- }
- /*******************************************************************************
- 函 數(shù) 名:Timer1(void)
- 函數(shù)功能:定時(shí)器T1的中斷函數(shù),控制側(cè)音頻率,ToneFre為側(cè)音頻率的序列號。
- *******************************************************************************/
- void Timer1(void) interrupt 3
- {
- BEEP = ~BEEP;
- TH1 = Tone_H[ToneFreq];
- TL1 = Tone_L[ToneFreq];
- }
- /*******************************************************************************
- 函 數(shù) 名:Timer2
- 函數(shù)功能:定時(shí)器T2的中斷函數(shù)。
- *******************************************************************************/
- void Timer2(void) interrupt 5
- {
- TF2 = 0;
- T2Count++;
- }
- /*******************************************************************************
- 函 數(shù) 名:Delay
- 函數(shù)功能:1ms延時(shí)函數(shù)
- 輸 入:t 延時(shí)時(shí)長 t x 1ms
- *******************************************************************************/
- void Delay(uint t)
- {
- uint max = 10 * t; //計(jì)算時(shí)長閾值
- TCount = 0;
- TR0 = 1;
- while (TCount <= max); //產(chǎn)生延時(shí)
- TR0 = 0;
- }
- /*******************************************************************************
- 函 數(shù) 名:TimeCount
- 函數(shù)功能:計(jì)算Dot/Dash時(shí)長
- *******************************************************************************/
- void TimeCount(void)
- {
- DotTime = 12000 / WPM;
- DashTime = 3 * DotTime;
- }
- /*******************************************************************************
- 函 數(shù) 名:Paddle
- 函數(shù)功能:產(chǎn)生自動鍵電碼
- *******************************************************************************/
- void Paddle(void)
- {
- uint max = Tmax; //設(shè)定時(shí)長閾值
- TR1 = 1; //開音頻振蕩器
- TCount = 0; //時(shí)長計(jì)數(shù)器清零
- CWOUT = SendFlg; //設(shè)定發(fā)射狀態(tài)
- TR0 = 1; //開時(shí)長計(jì)數(shù)器
- while (TCount <= max); //發(fā)送
- TR0 = 0; //關(guān)時(shí)長計(jì)數(shù)器
- CWOUT = 1; //禁止發(fā)射
- TR1 = 0; //關(guān)音頻振蕩器
- Space(1); //點(diǎn)劃間隔
- T2Count = 0;
- }
- /*******************************************************************************
- 函 數(shù) 名:Space
- 函數(shù)功能:產(chǎn)生間隔
- 輸 入:n 間隔數(shù)量
- *******************************************************************************/
- void Space(uchar n)
- {
- uint max = n * DotTime; //計(jì)算時(shí)長閾值
- TCount = 0; //時(shí)長計(jì)數(shù)器清零
- TR0 = 1; //開時(shí)長計(jì)數(shù)器
- while (TCount <= max); //產(chǎn)生間隔
- TR0 = 0; //關(guān)時(shí)長計(jì)數(shù)器
- }
- /*******************************************************************************
- 函 數(shù) 名:Function
- 函數(shù)功能:按照功能鍵執(zhí)行相關(guān)設(shè)置
- *******************************************************************************/
- void Function(void)
- {
- bit p = 0;
- INT_OFF(); //關(guān)INT
- SendFlg = 1; //禁止發(fā)射
- KeyValue = 0;
- while (K1 == 0) //長按鍵,每1秒變換一個功能
- {
- Delay(100); //每100ms計(jì)數(shù)一次
- if (++KeyValue > 40) //保持循環(huán)按鍵
- KeyValue = 0;
- if (KeyValue % 10 == 0) //到達(dá)變換時(shí)間
- {
- switch (KeyValue)
- {
- case 10: SEND_DASH(); break; //設(shè)定發(fā)報(bào)速度提示
- case 20: SEND_DASH(); SEND_DASH(); break; //設(shè)定側(cè)音頻率提示
- case 30: SEND_DASH(); SEND_DASH(); SEND_DASH(); break; //錄入呼號提示
- }
- }
- }
- KeyValue /= 10;
- T2Count = 0;
- switch (KeyValue)
- {
- case 1: //調(diào)整發(fā)報(bào)速度
- while (K1 == 1 && T2Count <= 96) //K1按下或6秒內(nèi)無鍵按下則退出
- {
- Display();
- if (K4 == 0 && WPM < 60) //WPM+
- {
- while (T2Count < 16 && K4 == 0); //松手延遲
- WPM++;
- TimeCount();
- SEND_DASH();
- p = 1;
- }
- if (K3 == 0 && WPM > 4) //WPM-
- {
- while (T2Count < 16 && K3 == 0 ); //松手延遲
- WPM--;
- TimeCount();
- SEND_DASH();
- p = 1;
- }
- }
- if (p == 1)
- WriteSystem(); //記憶參數(shù)
- SEND_DASH();
- break;
- case 2: //設(shè)定側(cè)音頻率
- while (K1 == 1 && T2Count <= 96) //K1按下或6秒內(nèi)無鍵按下則退出
- {
- Display();
- if (K3 == 0 && ToneFreq > 0) //頻率減按下
- {
- while (T2Count < 16 && K3 == 0); //松手延遲
- ToneFreq--;
- TH1 = Tone_H[ToneFreq];
- TL1 = Tone_L[ToneFreq];
- SEND_DASH();
- p = 1;
- }
- if (K4 == 0 && ToneFreq < 6) //頻率加按下
- {
- while (T2Count < 16 && K4 == 0); //松手延遲
- ToneFreq++;
- TH1 = Tone_H[ToneFreq];
- TL1 = Tone_L[ToneFreq];
- SEND_DASH();
- p = 1;
- }
- }
- if (p == 1)
- WriteSystem(); //記憶參數(shù)
- SEND_DASH();
- break;
- case 3: //錄入呼號
- RecordInfor();
- }
- INT_ON(); //開INT
- }
- /*******************************************************************************
- 函 數(shù) 名:RecordInfor
- 函數(shù)功能:錄入內(nèi)置信息,最多10個字符
- *******************************************************************************/
- void RecordInfor(void)
- {
- bit k = 0; //間隔標(biāo)志清零
- Number = 0; //字符數(shù)清零
- T2Count = 0; //退出計(jì)時(shí)清零
- while (K1 && Number < Cmax && T2Count <= 320) //按K1鍵/點(diǎn)劃數(shù)為最大值/者20秒無按鍵則退出
- {
- if (!K3) //Dot鍵按下
- {
- Delay(5); //消抖
- if (!K3)
- {
- CW_x[Number++] = '0';
- SEND_DOT();
- TCount = 0; //間隔計(jì)時(shí)清零
- TR0 = 1; //開定時(shí)器T0用于添加字符間隔
- k = 1; //設(shè)置間隔標(biāo)志
- }
- }
- if (!K4) //Dash鍵按下
- {
- Delay(5);
- if (!K4)
- {
- CW_x[Number++] = '1';
- SEND_DASH();
- TCount = 0;
- TR0 = 1;
- k = 1;
- }
- }
- if (k && TCount >= DashTime) //添加字符間隔
- {
- CW_x[Number++] = '.';
- TR0 = 0; //關(guān)定時(shí)器T0
- k = 0; //清除間隔標(biāo)志
- }
- }
- if (Number > 0) //有信息錄入則補(bǔ)字符間隔、記憶字符數(shù)
- {
- if (CW_x[Number - 1] != '.')
- CW_x[Number] = '.' ;
- WriteSystem();
- }
- }
- /*******************************************************************************
- 函 數(shù) 名:WriteSystem
- 函數(shù)功能:寫入系統(tǒng)參數(shù)
- *******************************************************************************/
- void WriteSystem(void)
- {
- EEPROM_SectorErase(SectorAddr_1);
- CW_x[0] = WPM;
- CW_x[1] = ToneFreq;
- CW_x[2] = Number;
- EEPROM_Write(SectorAddr_1, CW_x, 3);
- }
- /*******************************************************************************
- 函 數(shù) 名:Player
- 函數(shù)功能:發(fā)送內(nèi)置信息
- 輸 入:m 發(fā)送字符數(shù),x[]信息
- *******************************************************************************/
- void Player(uchar m, uchar x[])
- {
- uchar j = 0;
- for (; j < m; j++)
- switch (x[j])
- {
- case '0': SEND_DOT(); break; //發(fā)送Dot
- case '1': SEND_DASH(); break; //發(fā)送Dash
- case '.': Space(2); break; //字符間隔
- case ' ': Space(6); //單詞間隔
- }
- }
- /*******************************************************************************
- 函 數(shù) 名:PlayCall
- 函數(shù)功能:發(fā)送呼叫
- *******************************************************************************/
- void PlayCall(void)
- {
- uchar i;
- EEPROM_Read(SectorAddr_2, CW_x, Number);
- for (i = 1; i < 4; i++)
- Player(10, C1);
- Player(6, C2);
- for (i = 1; i < 4; i++)
- {
- Player(Number, CW_x);
- Space(4);
- }
- Player(14, C3);
- }
- /*******************************************************************************
- 函 數(shù) 名:Display
- 函數(shù)功能:使用數(shù)碼管顯示
- *******************************************************************************/
- void Display(void)
- {
- uchar i;
- uint f = 400 + ToneFreq * 100;
- for (i = 1; i < 9; i++)
- {
- switch (i)
- {
- case 1: if (WPM/10 != 0) {LSC = 1; LSB = 1; LSA = 1; GPIO_DIG = DIG_CODE[WPM / 10];} break; //顯示W(wǎng)PM十位
- case 2: LSC = 1; LSB = 1; LSA = 0; GPIO_DIG = DIG_CODE[WPM % 10]; break; //顯示W(wǎng)PM個位
- case 5: if (f == 1000) {LSC = 0; LSB = 1; LSA = 1; GPIO_DIG = 0x06;} break; //顯示側(cè)音頻率千位
- case 6: LSC = 0; LSB = 1; LSA = 0; GPIO_DIG = DIG_CODE[(f / 100) % 10]; break; //顯示側(cè)音頻率百位
- case 7: LSC = 0; LSB = 0; LSA = 1;GPIO_DIG = 0x3F; break; //顯示側(cè)音頻率十位
- case 8: LSC = 0; LSB = 0; LSA = 0;GPIO_DIG = 0x3F; //顯示側(cè)音頻率個位
- }
- Delay(1);
- GPIO_DIG = 0x00; //消隱
- }
- }
- /*******************************************************************************
- 函 數(shù) 名:EEPROM_SectorErase
- 函數(shù)功能:擦除一個扇區(qū)(512字節(jié)/扇區(qū))
- 輸 入:扇區(qū)地址 EE_address
- *******************************************************************************/
- void EEPROM_SectorErase(uint EE_address)
- {
- EA = 0; //關(guān)總中斷
- ISP_ADDRH = EE_address / 256; //扇區(qū)地址高字節(jié)
- ISP_ADDRL = EE_address % 256; //扇區(qū)地址低字節(jié)
- ISP_ENABLE(); //允許ISP操作
- ISP_ERASE(); //扇區(qū)擦除命令
- ISP_TRIG(); //觸發(fā)ISP操作
- ISP_DISABLE(); //禁止ISP操作
- EA = 1; //開總中斷
- }
- /*******************************************************************************
- 函 數(shù) 名:EEPROM_Read
- 函數(shù)功能:讀n個字節(jié)函數(shù)(最多255字節(jié)/次)
- 輸 入:扇區(qū)地址 EE_address, 讀出數(shù)據(jù) *DataAddress, 讀出字節(jié)數(shù) n
- *******************************************************************************/
- void EEPROM_Read(uint EE_address, uchar *DataAddress, uchar n)
- {
- EA = 0; //關(guān)總中斷
- ISP_ENABLE(); //允許ISP操作
- ISP_READ(); //字節(jié)讀命令
- do
- {
- ISP_ADDRH = EE_address / 256; //地址高字節(jié)
- ISP_ADDRL = EE_address % 256; //地址低字節(jié)
- ISP_TRIG(); //觸發(fā)ISP操作
- _nop_();
- *DataAddress = ISP_DATA; //讀數(shù)據(jù)到指定變量
- EE_address++; //下一個地址
- DataAddress++; //下一個數(shù)據(jù)
- }
- while (--n); //直到結(jié)束
- ISP_DISABLE(); //禁止ISP操作
- EA = 1; //開總中斷
- }
- /*******************************************************************************
- 函 數(shù) 名:EEPROM_Write
- 函數(shù)功能:寫n個字節(jié)數(shù)據(jù)(最多255字節(jié)/次)
- 輸 入:扇區(qū)地址 EE_address,寫入數(shù)據(jù) *DataAddress,寫入字節(jié)數(shù) n
- *******************************************************************************/
- void EEPROM_Write(uint EE_address, uchar *DataAddress, uchar n)
- {
- EA = 0; //關(guān)總中斷
- ISP_ENABLE(); //允許ISP操作
- ISP_WRITE(); //字節(jié)寫命令
- do
- {
- ISP_ADDRH = EE_address / 256; //送地址高字節(jié)
- ISP_ADDRL = EE_address % 256; //送地址低字節(jié)
- ISP_DATA = *DataAddress; //送數(shù)據(jù)到ISP_DATA
- ISP_TRIG(); //觸發(fā)ISP操作
- _nop_();
- EE_address++; //下一個地址
- DataAddress++; //下一個數(shù)據(jù)
- }
- while (--n); //直到結(jié)束
- ISP_DISABLE(); //禁止ISP操作
- EA = 1; //開總中斷
- }
復(fù)制代碼
|
|