串口发送

#include<STC12C56.h>//使用<>用来引用标准库的头文件,编译器将从标库目录开始搜索
#include<intrins.h>
#include"AD9833-12864下位机.h"//使用“”用来引用非标准库的头文件,编译器将从用户的工作目录开始搜索


int main()//系统主函数
{
 Mcu_init();
 while (1)
 {
if (f10ms)
{
f10ms = 0;
BUF_dispose();
Key_dispose();
            FREQ_dispose();
            PWM_alert();
   Wave_mode();
       Result_9833(0, 45);
}
 }
 return 0;
}


//定时报警子程序
void PWM_alert(void)
{
pwm++;
if (alarm)
{
if (pwm < 15)
alert = 1;
else
alert = 0;
}
if (pwm > 30)
pwm = 0;
}


//频率转换以便于单片机快速处理按键控制任务
void FREQ_dispose(void)
{
if (FREQ > 6000)
{
FREQ = 6000;
alarm = 1;//频率超过6M时,报警指示灯亮,且频率仍视为6M
}
if ((FREQ>1) && (FREQ<6000))
{
alarm = 0;
alert = 0;
}
if (FREQ < 1)
{
  FREQ = 1;
  alarm = 1;//频率低于1K时,电路报警,且频率仍为1K
}
}


//延时nMs函数:为提高效率,将长循环放在内层,以减少CPU跨切循环层的次数
/*void Delay(uchar t)
{
      uchar col;
 uchar row;
      while (t--)
 {
        for (col = 10; col>0; col--)
{
          for (row = 0; row<169; row++);
}
 }
}*/


//单片机上电初始化
void Mcu_init(void)
{
 buf = 0x20;//默认开机显示三角波,步进1K,频率不增不减
 alert = 0;
 P1M0 = 0xe0;//1110 0000为了使5V单片机与3V的AD9833正常通讯,单片机对应端口设置成开漏输出,以便外部上拉使电平匹配
 P1M1 = 0xe0;//1110 0000
 P3M0 = 0x00;//0000 0000
 P3M1 = 0x04;//0000 0100
 TR0 = 1;//开定时/计数器0
 AUXR = 0x80;//定时器时钟1T模式
 TMOD = 0x21;//设置定时器模式:T0工作方式16位;T1是8位自动重载作为波特率发生器
 TL0 = 0x66;//设置定时初值,定时500us
 TH0 = 0xEA;
      EA = 1;//开总中断   
 ET0 = 1;//定时/计数器0允许中断
 SCON = 0x40;//串口工作在方式1:10位异步收发
 PCON = 0x00;//波特率不加倍
 TH1 = 0xFD;
 TL1 = 0xFD;//波特率4800
 TR1 = 1;  
}


//发送数据处理,每500ms发送一次
void BUF_dispose(void)
{
buftime++;
if (buftime > 49)
{
TxdBUF[1] = FREQ>>8;
TxdBUF[0] = FREQ&0xff;
TxdBUF[3] = step>>8;
TxdBUF[2] = step&0xff;
TxdBUF[4] = add_flag2;
Checksum = 0;
Checksum += TxdBUF[0];
Checksum += TxdBUF[1];
Checksum += TxdBUF[2];
Checksum += TxdBUF[3];
Checksum += TxdBUF[4];
TxdBUF[5] = Checksum>>8;
   TxdBUF[6] = Checksum&0xff;
TxdIndex=1;
   SBUF=TxdBUF[0];
buftime = 0;
}
}


//AD9833写函数
void Write_9833_d16(uint x)//向AD9833写数据/命令函数
{
 uchar i;
 uchar w;
 SCLK_H;//对SCLK置高电平,这是写数据的第一步
 FSYNC_H;
 FSYNC_L;//先对AD9833进行使能设置
 w = (x >> 8);//取x的高8位进行传输
 for (i=0; i<8; i++)
 {
   if ((w << i) & (0x80))
 SDATA_H;
else
 SDATA_L;;
SCLK_L;//模拟时钟
SCLK_H;
 }//发送高8位数据

 w = (x >> 0);//取x的低8位进行传输
 for (i=0; i<8; i++)
 {
   if ((w << i) & (0x80))
 SDATA_H;
else
 SDATA_L;;
SCLK_L;
SCLK_H;
 }//发送低8位数据
 FSYNC_H;//关闭使能端
}


//AD9833转换函数
void Result_9833(uchar freq_SFR, uchar wave_PHASE)
{
double freq  = 1000.0;
    int freq_LSB;
    int freq_MSB;
    int phase_DAT;
    double freq_MID;
    double freq_DAT;
    long int freq_HEX;
wait++;
if(wait == 10)
{
 wait = 0;
 freq  = FREQ*1000;


      /*计算频率的16进制值*/
      freq_MID = 268435456/25;//适合25M贴片有源晶振
      freq_DAT = freq;
      freq_DAT = freq_DAT/1000000;
      freq_DAT = freq_DAT*freq_MID;
      freq_HEX = freq_DAT;//这个freq_HEX是个很大的值,需要拆分成两个14位的进行处理
      freq_LSB = freq_HEX;//低16位送给freq_LSB
      freq_LSB = freq_LSB&0x3fff;//去掉高两位变成14位的数据
      freq_MSB = freq_HEX>>14;//高16位送给freq_MSB
      freq_MSB = freq_MSB&0x3fff;


      /*计算相位值*/
      phase_DAT = wave_PHASE | 0xC000;
  
      /*把数据设置到设置频率寄存器0*/
      if (freq_SFR == 0)
      {
        freq_LSB = freq_LSB | 0x4000;
   freq_MSB = freq_MSB | 0x4000;
   Write_9833_d16(0x0100);//复位ad9833,即reset位为1
   Write_9833_d16(0x2100);//选择数据一次写入,B28和reset位为1
   Write_9833_d16(freq_LSB);//L14(低14位),选择频率寄存器0的低14位数据输入
   Write_9833_d16(freq_MSB);//H14,频率寄存器的高14位数据输入
   Write_9833_d16(phase_DAT);//设置相位
   Write_9833_d16(0x2000);//设置FSELECT位为0,芯片开始工作,频率寄存器0输出波形
      }
      /*把数据设置到设置频率寄存器1*/
      if (freq_SFR == 1)
      {
        freq_LSB = freq_LSB | 0x8000;
    freq_MSB = freq_MSB | 0x8000;
    //使用频率寄存器1输出波形
    Write_9833_d16(0x0100);//复位ad9833,即reset位为1
    Write_9833_d16(0x2100);//选择数据一次写入,B28和reset位为1
   Write_9833_d16(freq_LSB);//L14(低14位),选择频率寄存器0的低14位数据输入
   Write_9833_d16(freq_MSB);//H14(高14位),频率寄存器的高14位数据输入
   Write_9833_d16(phase_DAT);//设置相位
   Write_9833_d16(0x2800);//设置FSELECT位为1,芯片开始工作,频率寄存器1输出波形
      }
}
}


//AD9833波形选择函数
void Wave_mode(void)
{
      if (add_flag2 == 0)//输出三角波
      {
          //Delay(10);//延时10ms
     Write_9833_d16(0x2002);//设置MODE位为1,输出三角波
 //buf1 = 0;
 //buf0 = 0;
      }
      if (add_flag2 == 1)//输出方波
      {
          //Delay(10);//延时10ms
     Write_9833_d16(0x2028);//设置OPBITEN位为1,输出方波
 //buf1 = 0;
 //buf0 = 1;
      }
      if (add_flag2 == 2)//输出正弦波
      {
          //Delay(10);//延时10ms
         Write_9833_d16(0x2000);//设置MODE位为0,输出正弦波
 //buf1 = 1;
 //buf0 = 0;
      }
}


//按键扫描函数
void Key_dispose(void)
{
//按键去抖
if(keysave == keytemp)
{
keyms10++;
if(keyms10 >4)
{
keyms10 = 5;
key = keysave;//去抖动后记录按键有效值
}
}
else
{
keyms10 = 0;
keysave = keytemp;
}
    //按键处理
if (key != keybefore)//短按生效
{
if (key == 0xfe)
{
switch (add_flag1)
{
case 0 : FREQ += 1;step = 1;         break;//频率每次增加1K,即步进为1K        
case 1 : FREQ += 10;step = 10;       break;//频率每次增加10K,即步进为10K
case 2 : FREQ += 100;step = 100;     break;//频率每次增加100K,即步进为100K
case 3 : FREQ += 1000;step = 1000;   break;//频率每次增加1M,即步进为1M
default :                            break;    
    }
}
if (key == 0xfd)
{
switch (add_flag1)
{
case 0 : FREQ -= 1;step = 1;         break;//频率减少1K,即步进为1K        
case 1 : FREQ -= 10;step = 10;       break;//频率减少10K,即步进为10K
case 2 : FREQ -= 100;step = 100;     break;//频率减少100K,即步进为100K
case 3 : FREQ -= 1000; step = 1000;  break;//频率减少1M,即步进为1M 
default :                            break;
}
}
if (key == 0xfb)
{
            add_flag1++;
if (add_flag1 > 3)
{
 add_flag1 = 0;
}
}
if (key == 0xf7)
{
add_flag2++;
if (add_flag2 > 2)
{
 add_flag2 = 0;
}
}
      }
     keybefore = key;
}


//定时器0中断服务函数
void timer0(void) interrupt 1 using 0//T1中断服务函数:按键处理,定时扫描要执行
{
 keytemp = 0xff; 
      TR0 = 0;
 TF0 = 0;//定时器0无溢出,中断由硬件清零此标志位,若是采用T0查询法则必须用软件清零
 count++;
if (!key1)
keytemp &= 0xfe;
else
keytemp &= 0xff;
if (!key2)
keytemp &= 0xfd;
else
keytemp &= 0xff;
if (!key3)
keytemp &= 0xfb;
else
keytemp &= 0xff;
if (!key4)
keytemp &= 0xf7;
else
keytemp &= 0xff;
 if (count > 20)
 {
   count = 0;
   f10ms = 1;
 }
   //if ((FREQ>1000) && (FREQ<6000000))  alert = 0; //如果将此句放于此处,而FREQ又是32位的,导致按键功能失效,因为定时器中断服务函数执行过长
 TL0 = 0x66; //设置定时初值 可以用示波器通过任意IO口输出测量加或不加该句中断执行所需时间
 TH0 = 0xEA; //设置定时初值
      TR0 = 1;//开定时器0
}


//串口中断函数,没过500ms连续发送一包数据,其他时间不发送
void uart(void) interrupt 4 using 1
{
if (TI)
{
TI = 0;
if (TxIndex < TXD_length)//一个主循环发送一帧数据,而一个数据包共有7帧数据,这就要循环发送7次,而最后两个字节是校验和
{
SBUF = TxdBUF[TxIndex];
TxIndex++;
}
}
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值