发新帖我要提问
12
返回列表
打印
[STC单片机]

单片机C语言程序设计实训100例——基于STC8051+PROTEUS仿真与...

[复制链接]
楼主: 21ic0095
手机看帖
扫描二维码
随时随地手机跟帖
21
21ic0095|  楼主 | 2022-5-15 19:50 | 只看该作者 |只看大图 回帖奖励 |倒序浏览

带日历时钟及温度显示的电子万年历

使用特权

评论回复
22
21ic0095|  楼主 | 2022-5-15 19:53 | 只看该作者

(4号模块实物图)OLED+触摸键+DS1302+2组存储器+温度+温湿度+A/D与D/A模块电路板

使用特权

评论回复
23
21ic0095|  楼主 | 2022-5-15 19:54 | 只看该作者

使用特权

评论回复
24
21ic0095|  楼主 | 2022-5-15 19:55 | 只看该作者

使用特权

评论回复
25
21ic0095|  楼主 | 2022-5-28 20:53 | 只看该作者

使用特权

评论回复
26
21ic0095|  楼主 | 2022-5-28 20:54 | 只看该作者

使用特权

评论回复
27
21ic0095|  楼主 | 2022-5-28 20:56 | 只看该作者

使用特权

评论回复
28
21ic0095|  楼主 | 2022-5-28 20:57 | 只看该作者
//-----------------------------------------------------------------
//  名称: STC15+W5500-Server模式应用
//-----------------------------------------------------------------

//网关:192.168.1.1
//掩码:        255.255.255.0
//物理地址:0C 29 AB 7C 00 01
//本机IP地址:192.168.1.199
//端口0的端口号:5000
//端口0的目的IP地址:192.168.1.190
//端口0的目的端口号:6000
//-----------------------------------------------------------------
#define u8  unsigned char
#define u16 unsigned int
#define MAIN_Fosc 12000000L        //系统时钟
#include <string.h>
#include <stdio.h>
#include <intrins.h>
#include <stdlib.h>
#include "STC15xxx.h"
#include "W5500.h"
#include "src/oled.h"
#include "src/bmp.h"
//10号模块板外部资源引脚定义
sbit BEEP  =  P0^6;
sbit RELAY =  P0^7;

sbit LED0  =  P1^4;
sbit LED1  =  P1^5;
sbit LED2  =  P1^6;
volatile u8 LED_Control_Flag = 0;
sbit MA    =  P3^2;
sbit MB    =  P3^3;
sbit DQ    =  P1^7;
extern u8 Read_Temperature();
extern u8 Temp_Value[];
void Delay300us()        {        //@12.000MHz
        u8 i, j; i = 4; j = 125;
        do {
                while (--j);
        } while (--i);
}
//-----------------------------------------------------------------
#define ADC_POWER         0x80         //ADC电源控制位
#define ADC_FLAG                 0x10         //ADC完成标志
#define ADC_START         0x08         //ADC起始控制位
#define ADC_SPEEDLL        0x00         //540个时钟
#define ADC_SPEEDL         0x20         //360个时钟
#define ADC_SPEEDH         0x40         //180个时钟
#define ADC_SPEEDHH        0x60         //90个时钟

extern void Delay1us();
extern void delay_us(u16 x);
extern void Delay1ms();
extern void delay_ms(u16 ms);

//-----------------------------------------------------------------
// 蜂鸣器程序
//-----------------------------------------------------------------
void Sound() {
        u16 i;
        for (i = 0; i < 300; i++) { Delay300us(); BEEP ^= 1;};
        BEEP = 1;//最后要判断驱动三极管
}
void Delay(unsigned int d);                        //延时函数(ms)
//-----------------------------------------------------------------
// 初始化ADC
//-----------------------------------------------------------------
void InitADC() {
        P1ASF = 0xF0;                                         //P1高4位设为AD口
        ADC_RES = 0;                                                 //结果寄存器清0
        ADC_CONTR = ADC_POWER | ADC_SPEEDLL;//上电,转换速度:540个时钟
        delay_ms(2);                                                 //ADC上电并延时
}
//-----------------------------------------------------------------
// 读取ADC结果
//-----------------------------------------------------------------
u16 GetADCResult(u8 ch) {
        ADC_RES = 0; ADC_RESL = 0;                        //A/D转换结果先清零(可省)
        //选择通道并启动转换(含上电与540个时钟速度配置)
        ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
        _nop_(); _nop_(); _nop_(); _nop_();
        while (!(ADC_CONTR & ADC_FLAG));        //等待ADC转换完成
        ADC_CONTR &= ~ADC_FLAG;                                         //清ADC结束标志
        return (ADC_RES<<2 | ADC_RESL) ;        //读取转换结果
}
//-----------------------------------------------------------------
// 读取ADC结果
//-----------------------------------------------------------------
u8 GetKeyStatus() {
        u8 keystatus = 0x00;
        if (GetADCResult(0)<400) keystatus |= 1<<0;
        if (GetADCResult(1)<400) keystatus |= 1<<1;
        if (GetADCResult(2)<400) keystatus |= 1<<2;
        if (GetADCResult(3)<400) keystatus |= 1<<3;
        return keystatus;
}
//-----------------------------------------------------------------
// W5500初始化
//-----------------------------------------------------------------
void W5500_Initialization(void) {
        W5500_Init();                //初始化W5500寄存器函数
        Detect_Gateway();        //检查网关服务器
        Socket_Init(0);                //指定Socket(0~7)初始化,初始化端口0
}
//-----------------------------------------------------------------
// W5500装载网络参数
// 网关、掩码、物理地址、本机IP地址、端口号、目的IP地址、目的端口号、端口工作模式
//-----------------------------------------------------------------
void Load_Net_Parameters(void) {
        Gateway_IP[0] = 125;//加载网关参数
        Gateway_IP[1] = 221;
        Gateway_IP[2] = 52;
        Gateway_IP[3] = 254;

        Sub_Mask[0]        =        255;//加载子网掩码
        Sub_Mask[1]        =        255;
        Sub_Mask[2]        =        255;
        Sub_Mask[3]        =        0;

        Phy_Addr[0]        =        0x0c;//加载物理地址
        Phy_Addr[1]        =        0x29;
        Phy_Addr[2]        =        0xab;
        Phy_Addr[3]        =        0x7c;
        Phy_Addr[4]        =        0x00;
        Phy_Addr[5]        =        0x01;

        IP_Addr[0]        =        125;//加载本机IP地址    125.221.52.100
        IP_Addr[1]        =        221;
        IP_Addr[2]        =        52;
        IP_Addr[3]        =        100;

        S0_Port[0] = 0x13;//加载端口0的端口号5000
        S0_Port[1] = 0x88;

//        S0_DIP[0]=192;//加载端口0的目的IP地址
//        S0_DIP[1]=168;
//        S0_DIP[2]=1;
//        S0_DIP[3]=190;
//       
//        S0_DPort[0] = 0x17;//加载端口0的目的端口号6000
//        S0_DPort[1] = 0x70;
        S0_Mode = TCP_SERVER;//加载端口0的工作模式,TCP服务端模式
}
//-----------------------------------------------------------------
// W5500端口初始化配置
// 分别设置4个端口,根据端口工作模式,将端口置于TCP服务器、TCP客户端或UDP模式.
// 从端口状态字节Socket_State可以判断端口的工作情况
//-----------------------------------------------------------------
void W5500_Socket_Set(void) {
        if(S0_State==0) {                                                                                                                //端口0初始化配置
                if(S0_Mode==TCP_SERVER) {                                                                        //TCP服务器模式
                        if(Socket_Listen(0)==TRUE) S0_State=S_INIT; else S0_State=0;
                }
                else if(S0_Mode==TCP_CLIENT) {                                                //TCP客户端模式
                        if(Socket_Connect(0)==TRUE) S0_State=S_INIT; else S0_State=0;
                }
                else {                                                                                                                                                //UDP模式
                        if(Socket_UDP(0)==TRUE) S0_State=S_INIT|S_CONN; else S0_State=0;
                }
        }
}
//-----------------------------------------------------------------
// W5500接收并发送接收到的数据
// 本过程先调用S_rx_process()从W5500的端口接收数据缓冲区读取数据,
////*                        然后将读取的数据从Rx_Buffer拷贝到Temp_Buffer缓冲区进行处理。
////*                        处理完毕,将数据从Temp_Buffer拷贝到Tx_Buffer缓冲区。调用S_tx_process()
////*                        发送数据
//-----------------------------------------------------------------
void Process_Net_IO_Data(SOCKET s) {
        unsigned short Size;
        //读取接收缓冲中的数据放入Rx_Buffer并返回字节数
        Size = Read_SOCK_Data_Buffer(s, Rx_Buffer);
        Rx_Buffer[Size] = '\0';
        if (strcmp((char*)Rx_Buffer,"BEEP") == 0) { Sound(); }
        else if (strcmp((char*)Rx_Buffer,"LED_M") == 0) { LED_Control_Flag = 1; } //滚动显示
        else if (strcmp((char*)Rx_Buffer,"LED_F") == 0) { LED_Control_Flag = 2; } //闪烁显示
        else if (strcmp((char*)Rx_Buffer,"LED_K") == 0) { LED_Control_Flag = 0; } //停止显示
        else if (strcmp((char*)Rx_Buffer,"RELAYON") == 0)                 { RELAY = 0; }
        else if (strcmp((char*)Rx_Buffer,"RELAYOFF") == 0)                 { RELAY = 1; }
        else if (strcmp((char*)Rx_Buffer,"MOTOR_F") == 0)                 { MA = 1; MB = 0;}
        else if (strcmp((char*)Rx_Buffer,"MOTOR_R") == 0)                 { MA = 0; MB = 1;}
        else if (strcmp((char*)Rx_Buffer,"MOTOR_STOP") == 0)         { MA = 0; MB = 0;}
        OLED_ShowString(6,0,Rx_Buffer,16);
//        //所接收数据全部放的发送缓冲Tx_Buffer
//        memcpy(Tx_Buffer, Rx_Buffer, Size);
//       
//        Write_SOCK_Data_Buffer(s, Tx_Buffer, Size);
}
//-----------------------------------------------------------------
// T0初始化(16位自动重装载模式/12分频,5ms@12MHz)
//-----------------------------------------------------------------
void Timer0Init() {
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //设置定时器模式
        TL0 = 0x78;                        //设置定时初值
        TH0 = 0xEC;                        //设置定时初值
        //上述两行由STC-ISP自动生成的语句还可写成以下语句
        //TL0 = (65536 - 5000) & 0x00FF;
        //TH0 = (65536 - 5000) >> 8;
        //或者:
        //TL0 = - 5000 & 0x00FF;
        //TH0 = - 5000 >> 8;
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
}
//-----------------------------------------------------------------
// 主程序
//-----------------------------------------------------------------
int main(void) {
        unsigned int W5500_Send_Delay_Counter =0;
        int x = 0;
        int i = 100;
        char disp_buff[20];
        //float temp;
        P0M1 = 0x00; P0M0 = 0x00;
        P1M1 = 0x00; P1M0 = 0x00; //P1 = 0xF0;
        P2M1 = 0x00; P2M0 = 0x00;
        P3M1 = 0x00; P3M0 = 0x00;
       
        MA = 0; MB = 0;        //初始时电机停转
        RELAY = 1;                        //初始时继电器断开

        OLED_Init();                        //初始化OLED  
        OLED_Clear();
//        OLED_ShowCHinese(0,0,0);//中
//        OLED_ShowCHinese(18,0,1);//景
//        OLED_ShowCHinese(36,0,2);//园
        OLED_ShowString(6,0,"0.91' EE-HELLO",16);
        //OLED_ShowString(8,2,"ZHONGJINGYUAN");  
        //        OLED_ShowString(20,4,"2014/05/01");  
        //        OLED_DrawBMP(0,0,128,8,BMP1);  //图片显示(图片显示慎用,生成的字表较大,会占用较多空间,FLASH空间8K以下慎用)
        //while (1);
        InitADC();
       
        Load_Net_Parameters();                                //装载网络参数
        W5500_Hardware_Reset();                                //硬件复位W5500
        W5500_Initialization();                                //W5500初始化
       
        Timer0Init();                                        //T0初始化
        IE = 0x82;                                                //允许T0中断
        TR0 = 1;                                                        //启动T0
       
        while (1) {
                W5500_Socket_Set();                                        //W5500端口初始化配置
                W5500_Interrupt_Process();        //W5500中断处理程序框架
                //如果Socket0接收到数据
                if((S0_Data & S_RECEIVE) == S_RECEIVE) {
                        S0_Data &=~S_RECEIVE;
                        Process_Net_IO_Data(0);                //W5500接收并发送接收到的数据
                        //这里可放显示语句
                }
                else if(W5500_Send_Delay_Counter >= 2000) {//定时发送字符串
                        if(S0_State == (S_INIT|S_CONN)) {
                                S0_Data &= ~S_TRANSMITOK;
                                //memcpy(Tx_Buffer, "\r\n欢迎使用E-HELLO模块板!\r\n", 25);
                                //Write_SOCK_Data_Buffer(0, Tx_Buffer, 25);//指定Socket(0~7)发送数据处理,端口0发送23字节数据
                                //--------------------------------------------
                                Tx_Buffer[0] = GetKeyStatus(); //放置4位按键状态
                                //--------------------------------------------
                                x = rand() % 1000;
                                Tx_Buffer[1] = x >> 8;
                                Tx_Buffer[2] = x & 0xFF;
                                sprintf(disp_buff,"Send=>PC:%4d",x);
                                OLED_ShowString(6,2,disp_buff,16);
                                //--------------------------------------------
                                //if (Read_Temperature())
                                {                        //读取正常则显示
                                        Tx_Buffer[3] = Temp_Value[0];
                                        Tx_Buffer[4] = Temp_Value[1];
                                        //计算温度浮点值
                                        //temp = (int)(Temp_Value[1]<<8 | Temp_Value[0]) * 0.0625;
                                        //sprintf(disp_buff,"TEMP:%4.1f",temp);
                                        //OLED_ShowString(6,0,disp_buff,16);
                                }
                                //else
                                {
                                        Tx_Buffer[3] = -1000>>8;
                                        Tx_Buffer[4] = -1000;
                                }
                                //--------------------------------------------
                                Write_SOCK_Data_Buffer(0, Tx_Buffer, 5);//发送5字节
                        }
                        W5500_Send_Delay_Counter = 0;
                }
                W5500_Send_Delay_Counter++;
        }
}
//-----------------------------------------------------------------
// T0中断函数(控制LED显示:滚动,闪烁,停止)
//-----------------------------------------------------------------
void LED_Control() interrupt 1 {
        static u8 T_Count = 0, LED_M_Pattern = 0x40, LED_F_Pattern = 0xFF;
        if ( ++T_Count == 10) {                                                                //累加形成5ms×10=50ms定时
                if (LED_Control_Flag == 1) {                                //控制移动显示
                        P1 = (P1 & 0x8F) | LED_M_Pattern;
                        if ((LED_M_Pattern >>= 1) == 0x08) LED_M_Pattern = 0x40;
                }
                else if (LED_Control_Flag == 2) {                //控制闪烁
                        LED_F_Pattern ^= 0x70; P1 = LED_F_Pattern;
                }
                else if (LED_Control_Flag == 0) {                //停止显示
                        P1 &= ~0x70;
                }
                T_Count = 0;
        }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则