欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
如何根據《Keyer自動鍵控制單片機程序》反推出電路原理圖 求幫助
[打印本頁]
作者:
王生
時間:
2019-6-29 13:50
標題:
如何根據《Keyer自動鍵控制單片機程序》反推出電路原理圖 求幫助
/*******************************************************************************
程序名稱:Keyer 自動鍵控制程序
*******************************************************************************/
#include <STC89C5xRC.H>
#include <intrins.h>
#include <stdlib.h>
#include <config.h>
/* 定義IO端口宏 */
#define GPIO_DIG P0 //定義數碼管IO
#define GPIO_KEY P1 //定義鍵盤IO
/* 定義數碼管 */
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
/* 定義IO端口 */
sbit BEEP = P1^5; //定義蜂鳴器
sbit CWOUT = P2^0; //定義電鍵信號發送端口與LED
sbit K1 = P3^0; //定義K1鍵為功能鍵
sbit K2 = P3^1; //定義K2鍵為播放鍵
sbit K3 = P3^2; //定義Dot鍵使用外部中斷INT0
sbit K4 = P3^3; //定義Dash鍵使用外部中斷INT1
/* 聲明功能函數 */
void IntConfiguration(void); //中斷配置
void Delay(uint t); //延時(t=毫秒數)
void TimeCount(void); //計算Dot/Dash時長
void Paddle(void); //自控電碼發生
void Straight(void); //手控電碼發生
void Space(uchar n); //間隔發生器(n=間隔數目)
void Function(void); //功能鍵控制
void PlayCall(void); //發送本臺呼號
void Display(void); //數碼管顯示
void RecordInfor(void); //錄入本臺呼號
void WriteSystem(void); //寫入系統參數
void Player(uchar m, uchar x[]); //發送內置信息(m=發送字符數)
/* 聲明ISP操作函數 */
void EEPROM_Read(uint EE_address, uchar *DataAddress, uchar n); //字節讀
void EEPROM_Write(uint EE_address, uchar *DataAddress, uchar n); //字節寫
void EEPROM_SectorErase(uint EE_address); //扇區擦除
/* 數碼管顯示碼表,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};
/* 側音頻率表,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};
/* 呼叫數組 */
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時長,Dash時長
uint TCount, Tmax; //時長計數,時長閾值
uchar KeyValue; //功能鍵值
uchar Cmax = 54, CW_x[56]; //數組上標,錄入緩存
uchar WPM = 16; //發報速度4-60wpm (默認16wpm)
uchar ToneFreq = 3; //側音頻率序號0-6 (默認3/700Hz)
uchar Number; //播發字符數
bit KeyFlg = 1; //點劃交替標志(1=無點劃交替)
bit SendFlg = 0; //發送標志(1=禁止發射)
static uint T2Count = 0; //定時器T2計數變量
void main(void)
{
/* 設定初始值 */
IntConfiguration(); //配置中斷
if (K1 == 0) //按K1鍵開機進行系統重置
{
WPM = 16;
ToneFreq = 3;
Number = 0;
WriteSystem();
EEPROM_SectorErase(SectorAddr_2);
}
else
{
EEPROM_Read(SectorAddr_1, CW_x, 3); //讀系統設定參數
if (CW_x[0] != 0xFF)
{
WPM = CW_x[0];
ToneFreq = CW_x[1];
Number = CW_x[2];
}
}
TimeCount(); //計算Dot/Dash時長
TH1 = Tone_H[ToneFreq]; //設定定時器T1(側音頻率)初始值
TL1 = Tone_L[ToneFreq];
TR2 = 1; //開定時器T2
/* 運行按鍵監測程序 */
while (1)
{
SendFlg = 0; //允許發射
Display();
Delay(15);
if (K1 == 0) //功能鍵按下
{
Delay(1000);
if (K1 == 0)
Function();
}
if (K2 == 0 && Number > 0)
PlayCall();
}
}
/*******************************************************************************
函 數 名:IntConfiguration
函數功能:設置中斷參數
*******************************************************************************/
void IntConfiguration(void)
{
IT0 = 0; //INT0為低電平觸發方式
IT1 = 0; //INT1為低電平觸發方式
EX0 = 1; //INT0中斷允許
EX1 = 1; //INT1中斷允許
TMOD = 0x12; //定時器T0工作方式為2,定時器T1工作方式為1
PT0 = 1; //定時器T0(時長)高優先級
PT1 = 1; //定時器T1(側音)高優先級
ET0 = 1; //定時器T0中斷允許
ET1 = 1; //定時器T1中斷允許
T2CON = 0x00; //定時器T2工作方式為16位自動重載定時器
ET2 = 1; //定時器T2中斷允許
TH0 = 0x9C; //設定定時器T0為100us
TL0 = 0x9C;
RCAP2H = 0x0B; //設定定時器T2為每秒中斷16次
RCAP2L = 0xDC;
EA = 1; //開總中斷
}
/*******************************************************************************
函 數 名:Int0
函數功能:外部中斷0觸發時發送Dot
*******************************************************************************/
void Int0(void) interrupt 0
{
Delay(5); //消抖
if (K3 == 0)
{
if (KeyFlg == 1) //不是點劃交替發送Dot
{SEND_DOT();}
if (K4 == 0) //點劃交替發送Dash
{
SEND_DASH();
KeyFlg = 1; //清除點劃交替標志
}
}
}
/*******************************************************************************
函 數 名:Int1
函數功能:外部中斷1觸發時發送Dash
*******************************************************************************/
void Int1(void) interrupt 2
{
Delay(5); //消抖
if (K4 == 0)
{
SEND_DASH();
if (K3 == 0) //點劃交替發送Dot
{
SEND_DOT();
KeyFlg = 0; //設置點劃交替標志
}
}
}
/*******************************************************************************
函 數 名:Timer0
函數功能:定時器T0的中斷函數,產生100us/次的延時,控制發碼時長。
*******************************************************************************/
void Timer0(void) interrupt 1
{
TCount++;
}
/*******************************************************************************
函 數 名:Timer1(void)
函數功能:定時器T1的中斷函數,控制側音頻率,ToneFre為側音頻率的序列號。
*******************************************************************************/
void Timer1(void) interrupt 3
{
BEEP = ~BEEP;
TH1 = Tone_H[ToneFreq];
TL1 = Tone_L[ToneFreq];
}
/*******************************************************************************
函 數 名:Timer2
函數功能:定時器T2的中斷函數。
*******************************************************************************/
void Timer2(void) interrupt 5
{
TF2 = 0;
T2Count++;
}
/*******************************************************************************
函 數 名:Delay
函數功能:1ms延時函數
輸 入:t 延時時長 t x 1ms
*******************************************************************************/
void Delay(uint t)
{
uint max = 10 * t; //計算時長閾值
TCount = 0;
TR0 = 1;
while (TCount <= max); //產生延時
TR0 = 0;
}
/*******************************************************************************
函 數 名:TimeCount
函數功能:計算Dot/Dash時長
*******************************************************************************/
void TimeCount(void)
{
DotTime = 12000 / WPM;
DashTime = 3 * DotTime;
}
/*******************************************************************************
函 數 名:Paddle
函數功能:產生自動鍵電碼
*******************************************************************************/
void Paddle(void)
{
uint max = Tmax; //設定時長閾值
TR1 = 1; //開音頻振蕩器
TCount = 0; //時長計數器清零
CWOUT = SendFlg; //設定發射狀態
TR0 = 1; //開時長計數器
while (TCount <= max); //發送
TR0 = 0; //關時長計數器
CWOUT = 1; //禁止發射
TR1 = 0; //關音頻振蕩器
Space(1); //點劃間隔
T2Count = 0;
}
/*******************************************************************************
函 數 名:Space
函數功能:產生間隔
輸 入:n 間隔數量
*******************************************************************************/
void Space(uchar n)
{
uint max = n * DotTime; //計算時長閾值
TCount = 0; //時長計數器清零
TR0 = 1; //開時長計數器
while (TCount <= max); //產生間隔
TR0 = 0; //關時長計數器
}
/*******************************************************************************
函 數 名:Function
函數功能:按照功能鍵執行相關設置
*******************************************************************************/
void Function(void)
{
bit p = 0;
INT_OFF(); //關INT
SendFlg = 1; //禁止發射
KeyValue = 0;
while (K1 == 0) //長按鍵,每1秒變換一個功能
{
Delay(100); //每100ms計數一次
if (++KeyValue > 40) //保持循環按鍵
KeyValue = 0;
if (KeyValue % 10 == 0) //到達變換時間
{
switch (KeyValue)
{
case 10: SEND_DASH(); break; //設定發報速度提示
case 20: SEND_DASH(); SEND_DASH(); break; //設定側音頻率提示
case 30: SEND_DASH(); SEND_DASH(); SEND_DASH(); break; //錄入呼號提示
}
}
}
KeyValue /= 10;
T2Count = 0;
switch (KeyValue)
{
case 1: //調整發報速度
while (K1 == 1 && T2Count <= 96) //K1按下或6秒內無鍵按下則退出
{
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(); //記憶參數
SEND_DASH();
break;
case 2: //設定側音頻率
while (K1 == 1 && T2Count <= 96) //K1按下或6秒內無鍵按下則退出
{
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(); //記憶參數
SEND_DASH();
break;
case 3: //錄入呼號
RecordInfor();
}
INT_ON(); //開INT
}
/*******************************************************************************
函 數 名:RecordInfor
函數功能:錄入內置信息,最多10個字符
*******************************************************************************/
void RecordInfor(void)
{
bit k = 0; //間隔標志清零
Number = 0; //字符數清零
T2Count = 0; //退出計時清零
while (K1 && Number < Cmax && T2Count <= 320) //按K1鍵/點劃數為最大值/者20秒無按鍵則退出
{
if (!K3) //Dot鍵按下
{
Delay(5); //消抖
if (!K3)
{
CW_x[Number++] = '0';
SEND_DOT();
TCount = 0; //間隔計時清零
TR0 = 1; //開定時器T0用于添加字符間隔
k = 1; //設置間隔標志
}
}
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; //關定時器T0
k = 0; //清除間隔標志
}
}
if (Number > 0) //有信息錄入則補字符間隔、記憶字符數
{
if (CW_x[Number - 1] != '.')
CW_x[Number] = '.' ;
WriteSystem();
}
}
/*******************************************************************************
函 數 名:WriteSystem
函數功能:寫入系統參數
*******************************************************************************/
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);
}
/*******************************************************************************
函 數 名:Player
函數功能:發送內置信息
輸 入:m 發送字符數,x[]信息
*******************************************************************************/
void Player(uchar m, uchar x[])
{
uchar j = 0;
for (; j < m; j++)
switch (x[j])
{
case '0': SEND_DOT(); break; //發送Dot
case '1': SEND_DASH(); break; //發送Dash
case '.': Space(2); break; //字符間隔
case ' ': Space(6); //單詞間隔
}
}
/*******************************************************************************
函 數 名:PlayCall
函數功能:發送呼叫
*******************************************************************************/
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);
}
/*******************************************************************************
函 數 名:Display
函數功能:使用數碼管顯示
*******************************************************************************/
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; //顯示WPM十位
case 2: LSC = 1; LSB = 1; LSA = 0; GPIO_DIG = DIG_CODE[WPM % 10]; break; //顯示WPM個位
case 5: if (f == 1000) {LSC = 0; LSB = 1; LSA = 1; GPIO_DIG = 0x06;} break; //顯示側音頻率千位
case 6: LSC = 0; LSB = 1; LSA = 0; GPIO_DIG = DIG_CODE[(f / 100) % 10]; break; //顯示側音頻率百位
case 7: LSC = 0; LSB = 0; LSA = 1;GPIO_DIG = 0x3F; break; //顯示側音頻率十位
case 8: LSC = 0; LSB = 0; LSA = 0;GPIO_DIG = 0x3F; //顯示側音頻率個位
}
Delay(1);
GPIO_DIG = 0x00; //消隱
}
}
/*******************************************************************************
函 數 名:EEPROM_SectorErase
函數功能:擦除一個扇區(512字節/扇區)
輸 入:扇區地址 EE_address
*******************************************************************************/
void EEPROM_SectorErase(uint EE_address)
{
EA = 0; //關總中斷
ISP_ADDRH = EE_address / 256; //扇區地址高字節
ISP_ADDRL = EE_address % 256; //扇區地址低字節
ISP_ENABLE(); //允許ISP操作
ISP_ERASE(); //扇區擦除命令
ISP_TRIG(); //觸發ISP操作
ISP_DISABLE(); //禁止ISP操作
EA = 1; //開總中斷
}
/*******************************************************************************
函 數 名:EEPROM_Read
函數功能:讀n個字節函數(最多255字節/次)
輸 入:扇區地址 EE_address, 讀出數據 *DataAddress, 讀出字節數 n
*******************************************************************************/
void EEPROM_Read(uint EE_address, uchar *DataAddress, uchar n)
{
EA = 0; //關總中斷
ISP_ENABLE(); //允許ISP操作
ISP_READ(); //字節讀命令
do
{
ISP_ADDRH = EE_address / 256; //地址高字節
ISP_ADDRL = EE_address % 256; //地址低字節
ISP_TRIG(); //觸發ISP操作
_nop_();
*DataAddress = ISP_DATA; //讀數據到指定變量
EE_address++; //下一個地址
DataAddress++; //下一個數據
}
while (--n); //直到結束
ISP_DISABLE(); //禁止ISP操作
EA = 1; //開總中斷
}
/*******************************************************************************
函 數 名:EEPROM_Write
函數功能:寫n個字節數據(最多255字節/次)
輸 入:扇區地址 EE_address,寫入數據 *DataAddress,寫入字節數 n
*******************************************************************************/
void EEPROM_Write(uint EE_address, uchar *DataAddress, uchar n)
{
EA = 0; //關總中斷
ISP_ENABLE(); //允許ISP操作
ISP_WRITE(); //字節寫命令
do
{
ISP_ADDRH = EE_address / 256; //送地址高字節
ISP_ADDRL = EE_address % 256; //送地址低字節
ISP_DATA = *DataAddress; //送數據到ISP_DATA
ISP_TRIG(); //觸發ISP操作
_nop_();
EE_address++; //下一個地址
DataAddress++; //下一個數據
}
while (--n); //直到結束
ISP_DISABLE(); //禁止ISP操作
EA = 1; //開總中斷
}
復制代碼
歡迎光臨 (http://m.raoushi.com/bbs/)
Powered by Discuz! X3.1