51_固定频率的正弦波
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | /**********************51单片机学习例程************************ * 平台:Keil U4 + STC89C52 * 名称: PCF8591 ,固定输出10Hz的正弦波,数码管显示频率 * 编写:Tony * 日期:2022-2-12 * 晶体:12MHZ * 变更记录:无 ******************************************************************/ #include <reg52.h> #define GPIO_DIG P1 //数码管使用的段选IO sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; //138译码器,数码管的位选 #define GE {LSA=1;LSB=1;LSC=1;} //打开个位位选端 #define SHI {LSA=0;LSB=1;LSC=1;} //打开十位位选端 #define uchar unsigned char #define uint unsigned int uchar code DIG_CODE[] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; uchar num_ge,num_shi; uchar SEG_CNT; uchar code sin_table[] = {0x7F,0x98,0xB0,0xC6,0xD9,0xE9,0xF5,0xFC, 0xFE,0xFC,0xF5,0xE9,0xD9,0xC6,0xB0,0x98, 0x7F,0x66,0x4E,0x38,0x25,0x15,0x09,0x02, 0x00,0x02,0x09,0x15,0x25,0x38,0x4E,0x66}; //正弦波数据表 uint timer0_value; //定时器0初值寄存器 uchar vol_num; //数组标号 uchar TH0_BUFF; //TH0装载值的暂存器 uchar TL0_BUFF; //TL0装载值的暂存器 void Timer0_Init( void ); void SEG_display( void ); extern void DAC_OUT_START( void ); //调用其它文件中的函数 extern bit send_byte(uchar DAT); /*************************************************** * 定时器0初始化子函数 * 根据定时器初值初始化定时器0 ****************************************************/ void Timer0_Init( void ) { TMOD=0x01; //使用定时器1,16位定时器 TH0_BUFF=(65535-timer0_value)/256; TL0_BUFF=(65535-timer0_value)%256; TH0=TH0_BUFF; TL0=TL0_BUFF; TF0=0; //清中断标志 EA=1; //开总中断 ET0=1; //开定时器0中断 TR0=1; //启动定时器0 } /*************************************************** * 中断子程序,1/32个周期中断一次 * DA输出电压值,同时给TH0和TL0赋初值 ****************************************************/ void Time0() interrupt 1 { TH0=TH0_BUFF; TL0=TL0_BUFF; send_byte(sin_table[vol_num]); //送入要转换的电压值 if (vol_num>=31) //电压值更新 vol_num=0; else vol_num++; } void SEG_display( void ) { switch (SEG_CNT) { case 0x01: GPIO_DIG=0x00; SHI; GPIO_DIG= DIG_CODE[1]; SEG_CNT++; break ; case 0x02: GPIO_DIG=0x00; GE; GPIO_DIG= DIG_CODE[0]; SEG_CNT=0x01; break ; default : break ; } } void main() { SEG_CNT=0x01; timer0_value=3125-37; //补偿37 DAC_OUT_START(); Timer0_Init(); while (1) { SEG_display(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | #include <reg52.h> #include <intrins.h> //包含空指令函数_nop_(); #define uchar unsigned char #define uint unsigned int #define delay_6us {_nop_();_nop_();_nop_();\ _nop_();_nop_();_nop_();} //延时5个机器周期 #define PCF_ADDR 0x90 //定义PCF8591的地址 sbit SCL = P3^6; //定义总线连接端口 sbit SDA = P3^7; void IIC_start( void ); //函数声明 void IIC_stop( void ); bit ack_check( void ); bit send_byte(uchar DAT); void PCF8591_DAC_OUT(uchar DAT); void DAC_OUT_START( void ); void DAC_OUT_STOP(unsigned char DAT); /*************************************************** * IIC总线开始信号 ****************************************************/ void IIC_start( void ) { SDA=1; SCL=1; //置一两条线 delay_6us ; //延时6个机器周期 SDA=0; //拉低数据线 delay_6us ; // SCL=0; //拉低时钟线 } /*************************************************** * IIC总线停止信号 ****************************************************/ void IIC_stop( void ) { SDA=0; //拉低数据线 SCL=1; //置一时钟线 delay_6us ; SDA=1; //置一数据线 delay_6us ; } /*************************************************** * 检测IIC总线应答信号 ****************************************************/ bit ack_check( void ) { bit ack_bit; //位定义应答信号存储单元 SDA=1; //释放数据线,勾引从设备发送应答信号 delay_6us ; SCL=1; //置一时钟线 delay_6us ; ack_bit = SDA; //采样此时的数据线信号 SCL=0; //拉低时钟线 return ack_bit; //返回采样到的应答信号 } /*************************************************** * 向从设备发送一个字节, * 同时检测应答信号 ****************************************************/ bit send_byte(uchar DAT) { uchar i; uchar temp; //缓存寄存器 bit ack; //定义位变量,反馈应答信号 temp = DAT; //待发送字节存入缓冲寄存器 for (i = 0;i < 8;i++) //循环发送8位数据 { SCL = 0; //拉低时钟线 if ((temp&0x80)==0x80) //判断temp的高位是0还是1 SDA=1; else SDA=0; //送出相应数据 delay_6us ; SCL = 1; //拉高时钟线 temp <<=1; //待发送数据左移一位 delay_6us ; } SCL = 0; //拉低时钟线 ack = ack_check(); //调用应答信号检测子函数 return ack; //返回检测到的应答信号 } /*************************************************** * DA转换子函数 * 控制DA输出电压 ****************************************************/ void PCF8591_DAC_OUT(uchar DAT) { IIC_start(); if (send_byte(PCF_ADDR)==1) { IIC_stop(); return ; } send_byte(0x40); send_byte(DAT); IIC_stop(); } /*************************************************** * DA初始化子函数 ****************************************************/ void DAC_OUT_START( void ) { IIC_start(); if (send_byte(PCF_ADDR)==1) { IIC_stop(); return ; } send_byte(0x40); } /*************************************************** * DA停止子函数 ****************************************************/ void DAC_OUT_STOP(uchar DAT) { send_byte(DAT); IIC_stop(); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律