📄 新建_文本文档_(2).txt
字号:
/*一个完整的项目程序(原创,谢绝转载)
这是偶刚出道的时候为一个小公司做的程序.使用的是M16.当时签定了10年的保密协议,
不过现在那个公司已经倒闭了.现在看到这段程序的人,可以自由的修改,发布,包括
但不限于用于商业或非商业的项目中!呵呵~~~~*/
//******************************************************************************
//芯片:M16
//晶振:16.0000Mhz
//模块:率值配料下位机程序
//******************************************************************************
#include <eeprom.h>
#include <iom16v.h>
#include <macros.h>
//*******全局宏定义*************************************************************
#define uchar unsigned char
#define HANDEL 0xAA
//*******CH451数码管显示********************************************************
#define CH451_RESET 0x201 //复位
#define CH451_LEFTMOV 0x300 //设置移动方式-作移
#define CH451_LEFTCYC 0x301 //设置移动方式-左循
#define CH451_RIGHTMOV 0x302 //设置移动方式-右移
#define CH451_RIGHTCYC 0x303 //设置移动方式-右循
#define CH451_SYSOFF 0x400 //关显示、键盘、看门狗
#define CH451_SYSON1 0x401 //开显示
#define CH451_SYSON2 0x403 //开显示、键盘
#define CH451_SYSON3 0x407 //开显示、键盘、看门狗功能
#define CH451_DSP 0x500 //设置默认显示方式
#define CH451_BCD 0x580 //设置BCD译码方式
#define CH451_TWINKLE 0x600 //设置闪烁控制
#define CH451_DIG0 0x800 //数码管位0显示
#define CH451_DIG1 0x900 //数码管位1显示
#define CH451_DIG2 0xa00 //数码管位2显示
#define CH451_DIG3 0xb00 //数码管位3显示
#define CH451_DIG4 0xc00 //数码管位4显示
#define CH451_DIG5 0xd00 //数码管位5显示
#define CH451_DIG6 0xe00 //数码管位6显示
#define CH451_DIG7 0xf00 //数码管位7显示
//******************************************************************************
//全局变量
//******************************************************************************
static uchar DataBuff[600];//配比数据缓冲
static uchar RecvBuff[50];//正常命令接收缓冲
static uchar SendBuff[50];//命令发送缓冲
static int AD[8];//用来存放AD转换电流数据[0-7]8个电流量
static int ADUp[8];//上限
static int ADDown[8];//下限
static float ADValue[8];//电流数据的参照值
static uchar STAT=1;//状态-1.配比 2.电流
static uchar E_Index=0;//状态-配比
static uchar P_Index=0;//状态-电流
static uchar Warning=0;//报警标志
static uchar W_Index=1;//报警序号显示用
static uchar F_SendMode=1;//报警序号显示用
static uchar key_Delay=0xBF;
static char PressKey=0;//按键码
uchar timer=0;//数据的刷新周期
uchar UseWarning=1;//是否使用报警
int UseCount=0;//使用总次数
static uchar PasswordStat=1;//解密状态:1(需要一级密码),2(需要二级密码),3(需要三级密码),100(已全部解密)
static uchar Password1[6];//一级密码6个字节
static uchar Password2[6];//二级密码6个字节
static uchar Password3[6];//三级密码6个字节
static uchar MachineNumber[3];//机器编码
static uchar NeedSaveFlag=0;
//******************************************************************************
//初始化函数
//******************************************************************************
//初始化看门狗
void watchdog_init(void)
{
// WDR(); //喂狗
// WDTCR = 0x1F; //WATCHDOG ENABLED - dont forget to issue WDRs (0xF=2s)
}
//初始各端口
void port_init(void)
{
DDRA = 0x00;//
PORTA = 0x00;//
DDRB = 0xBF;//DSP(7,6,5,4) LED(0,1,2,3)
PORTB = 0x00;
DDRC = 0x00;//
PORTC = 0x00;//
DDRD = 0xF0;//PS2(4,5),Sound(7)
PORTD = 0x00;
PORTD&=~BIT(PD6);//0
}
//UART0 initialisation
// desired baud rate: 9600
// actual: baud rate:9615 (0.2%)
// char size: 8 bit
// parity: Disabled
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = 0x86;
//UBRRL = 0x67; //set baud rate //16 M
UBRRL = 0x33; //set baud rate //8 M
UBRRH = 0x00; //set baud rate hi
UCSRB = 0xF8;
}
//call this routine to initialise all peripherals
void init_devices(void)
{
int i=0;
//stop errant interrupts until set up
CLI(); //disable all interrupts
watchdog_init();
port_init();
WDR(); //喂狗
uart0_init();
WDR(); //喂狗
ch451_init();
WDR(); //喂狗
EPInit();
WDR(); //喂狗
keyboardInit();
WDR(); //喂狗
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
WDR(); //喂狗
putled(1,0,0);
putled(2,0,0);
putled(3,0,0);
putled(4,0,0);
putled(5,0,0);
putled(6,0,0);
putled(7,0,0);
putled(8,0,0);
WDR(); //喂狗
for(i=0;i<400;i++)
DataBuff[i]=0;
WDR(); //喂狗
for(i=0;i<30;i++)
RecvBuff[i]=0;
WDR(); //喂狗
for(i=0;i<30;i++)
SendBuff[i]=0;
WDR(); //喂狗
ReadUseCount();
WDR(); //喂狗
ReadSendMode();
WDR(); //喂狗
ReadKeyDelay();
WDR(); //喂狗
ReadUseWarning();//是否使用报警
WDR(); //喂狗
ReadElectricityUpDown();//读取电流上下限
WDR(); //喂狗
ReadElectricityValue();//读取电流参照值
WDR(); //喂狗
ReadPasswordStat();//读取解密状态
WDR(); //喂狗
STAT=1;//状态-1.配比 2.电流
WDR(); //喂狗
E_Index=0;//状态-配比-序号
P_Index=0;//状态-电流-序号
W_Index=1;//状态-报警-序号
Warning=0;//是否报警
PressKey=0;//按键码
NeedSaveFlag=0;//保存标志
WDR(); //喂狗
sound();
WDR(); //喂狗
delay_s(1);
WDR(); //喂狗
nosound();
WDR(); //喂狗
keyboardInit();
delay_s(1);
WDR(); //喂狗
sound();
WDR(); //喂狗
keyboardInit();
delay_s(1);
WDR(); //喂狗
nosound();
WDR(); //喂狗
keyboardInit();
//all peripherals are now initialised
}
//******************************************************************************
//延时子程序
//******************************************************************************
//延时1微秒
void delay_us(int time)
{
asm("_L2: subi R16,1");
asm(" brne _L2");
asm(" ret");
}
//延时1毫秒
void delay_ms(int time)
{
int t;
for(t=0;t<time;t++)
{
delay_us(1000);
}
}
//延时1秒
void delay_s(int time)
{
int t;
for(t=0;t<time;t++)
{
delay_ms(1000);
}
}
//******************************************************************************
//输入输出函数
//******************************************************************************
//向串口写一个字节
void putuchar(uchar data)
{
delay_ms(10);
while ( !( UCSRA & (1<<UDRE)) );
UDR = data; /* Put data into buffer, sends the data */
}
//从串口读取一个字节
uchar getuchar()
{
delay_ms(10);
while (!(UCSRA & (1<<RXC)) );
return UDR; /* Get and return received data from buffer */
}
//发送一串缓冲数据到串口
void sendComm()
{
uchar k=0;
delay_ms(300);
for(k=0;k<SendBuff[0];k++)
{
putuchar(SendBuff[k+1]);
}
}
//******************************************************************************
//AD转换函数
//******************************************************************************
//读取指定通道的AD值
int ReadADC( uchar channel)
{
int i;
ADMUX = 0; // Select channel 0
ADCSR = 0xc4;
ADMUX = channel; // Select channel
delay_ms(10);
ADCSR |= 0x40; // Start conversion
while (!(ADCSR & 0x10)); // Check if converstion is ready
ADCSR |= 0x10; // Clear Conversion ready flag by setting the bit
i = ADCL; // Read 8 low bits first (important)
i += (int)ADCH << 8; // Read 2 high bits and multiply with 256
return i;
}
//******************************************************************************
//模拟按键函数
//******************************************************************************
//初始化键盘,数据线=0,时钟线=1
void keyboardInit()
{
PORTD|=BIT(PD4);
return;
/*
上电复位时的协议:
1,PC->KB (0XFF);
复位, 进行 Basic Assurance Test (BAT). 设备返回 BAT 完成代码0xaa. 如果是键盘,切换到扫描码集2.上电时也进行BAT,所以,设备插上后马上送出 0xaa. 注意: 键盘回应 ACK ,所以必须把数据和时钟pin设置成high状 态, 并且至少500 秒! (设置方法参考i8042----端口). 之后, BAT 开始. 成功时返回 aah,失败返回fch . 有资料说0xfe ff, f4,f5,f6不存在!?
2,KB->PC (0XFA);
0xfa - n/a - PS/2 keyboard
所有键上报press ,release ,repeat 事件. 扫描码集 3 有效. 默认行为.
3,KB->PC (0XAA);
0xaa
BAT successful completion code. See comand 0xff.
4,PC->KB (0XF2);
0xf2 - 2*R - PS/2 Keyboard / Mouse
得到ID. 读到 0x83 and 0xab 代表键盘. 从mouse读到0x00 ,可能意味着ID以外的其他东西.
5,KB->PC (0XFA);
0xfa - n/a - PS/2 keyboard
所有键上报press ,release ,repeat 事件. 扫描码集 3 有效. 默认行为.
6,KB->PC (0XAB);
7,KB->PC (0X83);
9位d0-d6 为键盘扫描码 D7=0 键按下是发出。D7=1 键释放是发出。D8=1 表示一组数据结束
D7=0也包括超时发出的。
你每发一个数据应d该延时10MS-20ms,最快速度每秒30个字符
sendkey(0xFA,0);
sendkey(0xAA,0);
delay_us(10);
sendkey(0xFA,0);
sendkey(0xAB,0);
sendkey(0x83,0);
// PORTD|=BIT(PD5);//SCK=!SCK;//1
// PORTD|=BIT(PD4);//SCK=!SCK;//1
//PORTD&=~BIT(PD5);//SCK=!SCK;//0
//PORTD&=~BIT(PD4);//SCK=!SCK;//0
*/
}
//向键盘口发送一个字节,PS2发送程序,每次发送一个字节。
void sendkey(unsigned char KeyData,uchar WithDog)
{
// 低位在前,一个校验位,一个停止位
unsigned char i;
unsigned char ParityBit;
unsigned char DataBit;
unsigned char delaytime=0;
if(WithDog)
{
WDR(); //喂狗
delay_ms(key_Delay);
delay_ms(20);
delaytime=13;
}
else
{
delay_ms(key_Delay*10);
delay_ms(200);
delaytime=130;
}
while(!(PORTD&BIT(PD4))>>4)
{
if(WithDog)
delay_s(10);
else
delay_s(1);
}
PORTD|=BIT(PD4);
PORTD|=BIT(PD5);
for(i=0;i<8;i++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -