📄 main.c
字号:
//------------------------------------------------------------------------------// MN核心模块以太网测试程序
// CGI WEB服务器测试程序
// 版本:V2.1
// 核心模块物理参数:
// 1.主频:22.1184MHZ
// 2.RAM:片内4K,片外32K+256K(MAX)
//
// COPYRIGHT 2007-2009
//------------------------------------------------------------------------------
// 版本记录:
// 版本 日期 内容
// 2007/05/15 1.0 基本WEB测试程序
// 2007/05/20 2.0 增加LED控制的CGI程序
// 2007/06/26 2.1 增加电压和温度采集部分,网页信息自动刷新(JavaScript)
// 增加mn_init_m函数,修正程序脱离调试器无法运行的问题
//-------------------------------------------------------------------------------------
// 实验效果:
// 从计算机浏览器中访问http://192.168.0.90,显示数据采集和控制页面
// 1.可以通过页面控制LED2
// 2.页面每两秒自动刷新一次温度和电压数据
//
// 实验条件:
// 1.JP1和JP2所有位处于ON状态
// 2.计算机与核心模块通过交叉网线连接(或两者都使用直联网线连接到HUB或路由器上)
// 3.计算机的IP地址必须为192.168.0.XXX,其中XXX可以为2-254中的数据,但不能为90(因为核心模块为90)
// 4.调解电位器可以观察到网页上的数据变化
//
// 编译条件:
// 1.使用KEIL C8.0以上版本C51编译器
// 2.使用LARGE RAM模式
// 3.连接选项不使用覆盖分析,即增加连接选项NOOL
//--------------------------------------------------------------------------------------------
// //#include "mn_userconst.h" // TCP/IP Library Constants#include "mn_stackconst.h" // TCP/IP Library Constants#include "mn_errs.h" // Library Error Codes#include "mn_defs.h" // Library Type definitions#include "mn_funcs.h" // Library Function Prototypes#include "VFILE_DIR\index.h"#include <c8051F020.h> // Device-specific SFR Definitions
#include <stdio.h>
#include <ctype.h> // for toupper()
//-------------------------------
// 常量定义
//-------------------------------
#define SYSCLK 22118400
// AD内部参考电压,由于单片机个体差异,该参考电压可能不同
// 用户可测量J1双排插针的2,3引脚间的电压来调整该值,该值为
// 测量电压的1000倍
#define AD_VREF 2438
#define AD_VOLTAGE 0
#define AD_TEMPERATURE 8
//-----------------------------
// 引脚定义
//-----------------------------
sbit P_LED2 = P3^1; // LED2 指示灯
sbit P_RST = P3^0; // CP2201复位引脚
sbit INT_PIN = P2^2; // CP2201中断引脚
//------------------------------------------------------------------------------// Function Prototypes//------------------------------------------------------------------------------// Initialization Routinesvoid PORT_Init (void);void SYSCLK_Init (void);void EMIF_Init(void);
void Timer_Init();
void UART0_Init();
void SendString(char *pSendString);
int establish_network_connection();
void get_data (PSOCKET_INFO socket_ptr);
void get_led(PSOCKET_INFO socket_ptr);
void set_led(PSOCKET_INFO socket_ptr);
void Dlyms(unsigned int ms);
void ADC_Init();
void Voltage_Reference_Init();
void DAC_Init();
unsigned long SampleVoltageAndOut();
long SampleTemperature();
void InitVariable();
//---------------------------------------------
// 全局变量定义
//----------------------------------------------
unsigned char HTML_BUFFER[400];
unsigned char msg_ans[20];
unsigned long g_Voltage; // 电压
long g_Temperature; // 温度
unsigned char g_ADChannel;
//------------------------------------------------
// mn_init_m:修正库函数中的mn_init函数
//-------------------------------------------------
//------------------------------------
// mn_init_m修正函数使用的变量声明
//-----------------------------------
#include <string.h>
extern byte code NUM_SOCKETS;
extern byte code DEVICE_ID;
extern byte code NUM_VF_PAGES;
extern byte code NUM_POST_FUNCS;
int mn_ip_init();
void mn_timer_init();
void mn_http_init();
void mn_arp_init();
int mn_init_m(void)
{
unsigned char chip_id,val,i;
int data num;
bit c;
c = EA;
EA = 0;
chip_id = DEVICE_ID;
if (chip_id != C8051F020)
return MN_VERIFY_ERROR;
// 此处省略了原代码中的器件判断部分
//sock_info,在任何情况下必需调用
num = (unsigned int)NUM_SOCKETS*sizeof(SOCKET_INFO_T);//0x3D;
val = 0;
memset(sock_info,val,num);
//mn_ip_init: 在任何情况下必需调用
num = mn_ip_init();
if (num!=0)
{
//mn_timer_init:必需调用
mn_timer_init();
//使用DHCP时调用
//mn_dhcp_init();
//使用BOOTP时调用
//mn_bootp_init();
//vf_dir init, 在任何情况下必需调用
num = (unsigned int)NUM_VF_PAGES*sizeof(VF);//(0x1F);
val = 0;
memset(vf_dir,val,num);
for (i=0;i<NUM_VF_PAGES;i++)
vf_dir[i].cp2200_page_ptr = 0x2000;
//page_send_info init,在任何情况下必需调用
num = (unsigned int)NUM_SOCKETS*sizeof(PAGE_SEND_T);
val = 0;
memset(page_send_info,val,num);
for (i=0;i<NUM_SOCKETS;i++)
page_send_info[i].cp2200_page_ptr = 0x2000;
// pf init,在任何情况下必需调用
num = (unsigned int)NUM_POST_FUNCS*sizeof(POST_FUNCS);//(0x1F);
val = 0;
memset(pf,val,num);
//使用HTTP时调用
mn_http_init();
//使用TFTP时调用
//mn_ftp_server_init();
//使用SMTP时调用
//mn_smtp_init();
//在任何情况下必需调用
mn_arp_init();
EA = c;
return 0x0001;
}
else
{
EA = c;
return MN_INIT_ERROR;
}
}
////////////////////////////////////////////////////////////////////////////////
// AD中断服务程序
void AD_Isr() interrupt 15
{
unsigned int nRet;
unsigned long lt;
long t;
AD0INT = 0; // 清除中断标志
if(g_ADChannel==AD_VOLTAGE)
{// 上次采集的是电压值
// 从DA输出电压
DAC0L = ADC0L;
DAC0H = ADC0H;
nRet = ADC0H;
nRet<<=8;
nRet+=ADC0L;
lt = nRet+1;
lt =lt*AD_VREF;
lt >>=12;
g_Voltage = lt;
g_ADChannel = AD_TEMPERATURE;
}
else if(g_ADChannel==AD_TEMPERATURE)
{// 上次采集的是温度
nRet = ADC0H<<8;
nRet+=ADC0L;
lt =nRet+1;
lt =lt*AD_VREF;
lt >>=12;
t=lt-776;
g_Temperature = (g_Temperature+t)>>1; // /2
g_ADChannel = AD_VOLTAGE;
}
else
{
g_ADChannel = AD_VOLTAGE;
}
AMX0SL = g_ADChannel;
AD0BUSY = 1; // 启动转换
}
//-----------------------------------------------------------------------------
// 主函数
//-----------------------------------------------------------------------------
void main(void)
{
data int retval;
// 关闭看门狗
WDTCN = 0xde;
WDTCN = 0xad;
// 初始化硬件
EMIF_Init();
PORT_Init();
SYSCLK_Init();
Timer_Init();
UART0_Init();
// 初始化模拟部分
InitVariable();
ADC_Init();
Voltage_Reference_Init();
DAC_Init();
// 系统启动
SendString("CGI Test System!\r\n");
P_LED2 = 0;
// 首先进行一次温度采集,初始化温度值
SampleTemperature();
EIE2|=0x02; //使能AD中断
AMX0SL = g_ADChannel;
AD0BUSY = 1; // 启动转换
while(1)
{
// 此处不使用mn_init函数而改用mn_init_m函数
// 以解决原库函数不能脱离调试器运行的问题
// 用户应该根据程序实际使用的协议来调整该函数
// 具体参加该函数
while((retval=mn_init_m()) < 0)
{
// If code execution enters this while(1) loop, the stack failed to initialize.
// Verify that all boards are connected and powered properly.
P_LED2 = !P_LED2;
SendString(HTML_BUFFER);
Dlyms(1000);
}
P_LED2 = 1;
// Connect to the network
establish_network_connection();
// Add web page to virtual file system.
// The main page MUST be called index.htm or index.html.
mn_vf_set_entry((byte *)"index.html", INDEX_SIZE, index_html, VF_PTYPE_FLASH);
mn_pf_set_entry(
(byte*)"get_data", // Script Name (ASCII)
get_data // Function Pointer
);
mn_pf_set_entry(
(byte*)"set_led", // Script Name (ASCII)
set_led // Function Pointer
);
// Start the Application Layer Services
// If this routine exits, check the return value for an error code.
retval = mn_server();
}
}
//-----------------------------------------------------------------------------
// establish_network_connection
//-----------------------------------------------------------------------------
//
// This function calls mn_ether_init() to initialize the CP2200 and attach to
// the network.
//
// If there is a network connection, the function returns 1.
//
// In the call to mn_ether_init(), NUM_AUTONEG_ATTEMPTS is set to 0, so the
// function will not return until it successfully auto-negotiates.
//
// mn_ether_init() will not be a blocking call if NUM_AUTONEG_ATTEMPTS is set
// to a value greater than 0.
//
int establish_network_connection()
{
int retval;
do
{
// mn_ether_init() initializes the Ethernet controller.
// AUTO_NEG indicates that the controller will auto-negotiate.
retval = mn_ether_init(AUTO_NEG, 0, 0);
// If there is no link, poll link_status until it sets or the
// CP2200 resets and then call mn_ether_init() again.
if (retval == LINK_FAIL)
{
while(!link_status && !ether_reset);
}
// If retval is less than zero and is not LINK_FAIL, there is a
// hardware error.
else if (retval < 0)
{
// Verify that the Ethernet controller is connected and powered properly.
// Verity that the EMIF has been configured at a speed compatible with the
// Ethernet controller.
while(1);
}
}while(retval < 0);
return (1);
}
//-----------------------------------------------------------------------------// ether_reset_low//-----------------------------------------------------------------------------//// This routine drives the reset pin of the ethernet controller low.//void ether_reset_low(){ P_RST = 0;}//-----------------------------------------------------------------------------// ether_reset_high//-----------------------------------------------------------------------------//// This routine places the reset pin in High-Z allowing it to be pulled up // using the external pull-up resistor.//// Additionally, this routine waits for the reset pin to read high before// exiting.//void ether_reset_high (void){ P_RST = 1;
while(P_RST==0);}
//-----------------------------------------------------------------------------
// CGI Script: get_data
// 读取voltage&temperature状态 CGI程序
// 该函数返回电路板测试的电压和温度值
// 当使用CGI Script时调用该接口
//-----------------------------------------------------------------------------
void get_data (PSOCKET_INFO socket_ptr)
{
bit field_name_found;
unsigned int high,low;
xdata byte msg_buff[75];
// Search the URL for field-name = "type" and copy field-value to <msg_buff>
field_name_found = mn_http_find_value(BODYptr,(byte *)"type",msg_buff);
if(field_name_found)
{
// Type Check #1
// Check if the requested data type is "Temperature"
if( toupper(msg_buff[0]) == 'T')
{
// Search the URL for field-name = "format" and copy field-value to <msg_buff>
field_name_found = mn_http_find_value(BODYptr,(byte *)"format",msg_buff);
// Check if the requested format is HTML
if(field_name_found && toupper(msg_buff[0]) == 'H')
{
// User has requested temperature data in HTML format:
EA = 0;
g_Temperature*=100;
high = g_Temperature/286;
low = g_Temperature-high*286;
sprintf(HTML_BUFFER, "<html><body bgcolor=blue text=yellow><center><span style=\"font-family: sans-serif; font-size: 28pt; font-weight: bold;\">%d.%03d</span></center></body></html>",
high,low);
EA = 1;
SendString(HTML_BUFFER);
socket_ptr->send_ptr = (byte *)HTML_BUFFER;
socket_ptr->send_len = strlen(HTML_BUFFER);
}
}
else
{
if( toupper(msg_buff[0]) == 'V')
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -