📄 pproject.c
字号:
//****************************系统程序头文件****************************//
#include <io8535v.h> //AT90S8535寄存器定义头文件;
#include <macros.h> // AT90S8535宏定义,系统程序需要用到此宏定义过的函数;
//****************************定义全局变量****************************//
#define uchar unsigned char
#define uint unsigned int
#include "project.h"
uchar Key_Value; //按键键值;
uchar State_Flag; //站点标志;
uchar Ack_Flag; //确认标志;
uchar Pre_Flag; //预报标志;
uchar Move_Flag; //滚动标志;
uchar Spec_Flag; //特殊信息标志;
uchar EOM_Flag=1; //信息结束标志;
uchar Pst_Flag; //上、下行标志;
uchar State=1; //站数;
uchar Spec; //特殊信息数;
uchar Speed=20; //文字滚动速度;
uchar Word_Number; //显示字数;
//****************************说明****************************//
//语音芯片第1~16段分别保存16站的站名信息
//第17段保存报站信息“到了,请要下车的乘客依次从后门下车”
//第18、19段分别保存预报信息“前方到站”、“请要下车的乘客做好下车准备”
//第20段保存欢迎信息及公交车线路说明
//第21、22段保存特殊提示信息
uchar Snd_Info[]={0,17}; //报站声音信息
uchar Snd_Pre_Info[]={18,0,19}; //预报声音信息
uchar Snd_Spec[]={21,22}; //特殊声音信息
uchar Snd_Welc=20; //欢迎声音信息
//****************************说明****************************//
//本例公交车语音报站系统包含16站
//为方便起见,所有的站名都以“第n站”代替,其中n为当前站数,n<16
//报站时显示屏滚动显示“第n站到了”
//预报站时显示屏显示“前方到站第n站”
//其中“第n站”字模存放在二维数组State n[3][32]中
//“到了”字模存放在二维数组DL[2][32]中
//“前方到站”字模存放在二维数组QFDZ[4][32]中
uchar text[32]; //当前显示文字
uchar next[32]; //下一个显示文字
//****************************定义中断服务程序****************************//
#pragma interrupt_handler Key_Scan:2 //定义按键中断INT0的中断服务程序
#pragma interrupt_handler Receive_EOM:3 //定义语音中断INT1的中断服务程序
void delay(uchar i)
{for(;i!=0;i--) NOP();}
//****************************I2C驱动程序****************************//
//定义MAX6959时钟线为PA^7
void Set_SCL(uchar i)
{
if(i)
PORTA |=0x80;
else
PORTA &=0x7f;
}
//定义MAX6959数据线为PA^6
void Set_SDA(uchar i)
{
if(i)
PORTA |=0x40;
else
PORTA &=0xbf;
}
//I2C总线的开始条件:SCL高电平时SDA的下降沿
void Start()
{
Set_SDA(1); //SDA=1;
Set_SCL(1); //SCL=1;
delay(100); //等待时钟信号变成高电平以确保总线开始
Set_SDA(0); //SDA=0;
delay(100);
Set_SCL(0); // SCL=0;
}
//I2C总线结束条件:SCL为高电平时SDA的上升沿
void Stop()
{
Set_SDA(0); //SDA=0;
delay(100);
Set_SCL(1); //SCL=1;
delay(100); //等待时钟信号变成低电平以确保总线结束
Set_SDA(1); //SDA=1;
delay(100);
Set_SCL(0); //SCL=0;
}
//I2C总线应答:读完一个字节后将SDA线拉低,即应答0
void Ack()
{
Set_SDA(0); //SDA=0;
delay(50);
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
delay(50);
Set_SDA(1); //SDA=1;
}
//I2C总线应答:读完所要求的字节数据后将SDA线拉高,为结束IIC总线操作做准备
void Nack()
{
Set_SDA(1); //SDA=1;
delay(50);
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
delay(50);
Set_SDA(0); //SDA=0;
}
//检查I2C器件应答情况
void Check_Ack()
{
Set_SDA(1); //SDA=1;
Set_SCL(1); //SCL=1;
Ack_Flag=0; //清除应答标志;
DDRA &=0xbf; //设置SDA为输入
if(!((PINA & 0x40)>>6))
{
delay(50);
Set_SCL(0); //SCL=0;
delay(100);
}
else
{
Ack_Flag=1; //收到应答;
delay(50);
Set_SCL(0); //SCL=0;
delay(100);
}
DDRA |=0xff; //重新设置SDA为输出
}
//写1bit数据:0
void Write_Bit0()
{
Set_SDA(0); //SDA=0;
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
}
//写1bit数据:1
void Write_Bit1()
{
Set_SDA(1); //SDA=1;
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
Set_SDA(0); //SDA=0;
}
//写一字节数据Data
void Write_Byte(uchar Data)
{
uchar i;
for(i=0;i<8;i++)
{
if(Data & 0x80) //传输位从高位到低位,先传最高位
Write_Bit1();
else
Write_Bit0();
Data <<=1; //数据左移
}
}
//读一字节数据:返回值即读的数据
uchar Read_Byte()
{
uchar Read_Data=0xff; // Read_Data为读入的数据,初始值为0xff
uchar j;
for (j=0;j<8;j++)
{
Set_SDA(1); //SDA=1;
Set_SCL(1); //SCL=1;
DDRA &=0xbf; //设置SDA为输入线
//数据读出,若是0则移位;若是1则与0x01或
if((PINA & 0x40)==0)
{
Read_Data <<=1;
Read_Data=(Read_Data & 0xfe);
Set_SCL(0); //SCL=0;
}
else
{
Read_Data <<=1;
Read_Data =( Read_Data | 0x01);
Set_SCL(0); //SCL=0
}
}
DDRA |=0x40; //设置SDA为输出线
return(Read_Data); //返回读出的字节
}
//写一字节数据
void Write_1byte(uchar Slave,uchar Address,uchar Data)
{
Start(); //开始
Write_Byte(Slave); //写I2C器件地址
do
{
Check_Ack(); //检查应答位
}
while(Ack_Flag==1);
Write_Byte(Address); //送寄存器地址
do
{
Check_Ack(); //检查应答位
}
while(Ack_Flag==1);
Write_Byte(Data); //写入一字节数据
do
{
Check_Ack(); //检查应答位
}
while(Ack_Flag==1);
Stop(); //停止
}
//写两字节数据
void Write_2byte(uchar Slave,uchar Address,uchar Data0,uchar Data1)
{
Start(); //开始
Write_Byte(Slave); //写I2C器件地址
do
{
Check_Ack(); //检查应答位
}
while(Ack_Flag==1);//while(F0==1);
Write_Byte(Address); //送寄存器地址
do
{
Check_Ack(); //检查应答位
}
while(Ack_Flag==1);
Write_Byte(Data0);
do
{
Check_Ack(); //检查应答位
}
while(Ack_Flag==1);
Write_Byte(Data1);
do
{
Check_Ack(); //检查应答位
}
while(Ack_Flag==1);
Stop(); //停止信号
}
//读一字节数据
uchar Read_1byte(uchar Slave,uchar Address)
{
uchar data0,x;
do
{
Start(); //开始信号
Write_Byte(Slave); //写I2C器件地址
Check_Ack(); //检查应答位
}
while(Ack_Flag);//while(F0==1);
do
{
Write_Byte(Address); //写寄存器地址
Check_Ack(); //检查应答位
}
while(Ack_Flag);// while(F0==1);
do
{
Start(); //开始
Write_Byte(Slave+1); //写I2C器件地址(+1表示为读操作)
Check_Ack(); //检查应答位
}
while(Ack_Flag);
data0=Read_Byte(); //读1字节
Nack(); //读完发送一个Not Ack应答
Stop(); //停止
return data0; //返回读取数据
}
//****************************数字显示程序****************************//
void Led_Display(uchar Number)
{
uchar d0,d1;
d0=Number/10; //取站数的个位
d1=Number%10; //取站数的十位
Write_2byte(0x70,0x20,d1,d0); //从显示位0开始连续显示两位
}
//****************************键盘处理程序****************************//
void Key_Act(void)
{
GIMSK &=0x7f; //关闭中断
switch(Key_Value) //判断键值
{
case 1: //若键值为1,则报站
Inform(State); //报第State站
Lattice_Display(); //显示到站信息
Key_Value=0; //重新赋键值为0
break;
case 2: //若键值为2,则前进一站
if(State<16) //若站数<16,则
State++; //站数+1
else //否则
State=0; //重新赋站数为0
Led_Display(State); //显示当前站数
Key_Value=0; //重新赋键值为0
break;
case 4: //若键值为4,则播放特殊信息
Spec++; //特殊键按下一次,特殊段+1
Special(Spec); //报第Spec段特殊段
Key_Value=0; //重新赋键值为0
break;
case 8: //若键值为8,则进行上、下行切换
Pst_Flag=!Pst_Flag; //上、下行切换
Key_Value=0; //重新赋键值为0
break;
case 16: //若键值为16,则后退一站
if(State) //若站数不为0,则
State--; //站数-1
else //否则
State=16; //重新赋站数为16
Led_Display(State); //显示当前站数
Key_Value=0; //重新赋键值为0
break;
case 32: //若键值为32,则进行预报站
Pre_Inform(State+1); //预报第State+1站
Lattice_Display(); //显示预报站信息
Key_Value=0; //重新赋键值为0
break;
default:
NOP();
}
GIMSK |=0x80; //8535应为GIMSK
}
//****************************语音芯片驱动程序****************************//
//定义ISD2560使能线为PA^4
void Set_CE(uchar level)
{
if(level==1)
PORTA |=0x10;
else
PORTA &=0xef;
}
//定义ISD2560的PD线为PA^3
void Set_PD(uchar level)
{
if(level)
PORTA |=0x08;
else
PORTA &=0xf7;
}
//定义ISD2560的PR线为PA^2
void Set_PR(uchar level)
{
if(level)
PORTA |=0x04;
else
PORTA &=0xfb;
}
//定义ISD2560的A6/8/9线为PA^1
void Set_A6(uchar level)
{
if(level)
PORTA |=0x02;
else
PORTA &=0xfd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -