2024年1月4日发(作者:)

User 文件夹下 main.c #include "sys.h" #include "usart.h"

#include "delay.h" #include "led.h" #include "key.h" #include

"exti.h" #include "wdg.h" #include "timerx.h" #include "adc.h"

#include "rtc.h" #include "12864.h" #include "ov7670.h"

#include "usmart.h" #include "enc28j60.h"

#include "uip.h" #include "uip_arp.h" #include "tapdev.h"

#include "timer.h" #include "math.h" #include "string.h"

#include "syn.h"

//Mini STM32 开发板扩展实验 21

//ENC28J60 网络模块 实验

//正点原子 @ALIENTEK

//技术论坛 : //广州市星翼电子科技有限公司

void uip_polling(void);

void Display_Time(void);

void received_date(u8 *str);

u16 Process_date(u8 q,u8 b,u8 s,u8 g);

#define BUF ((struct uip_eth_hdr *)&uip_buf[0])

u8 t,Addres_1=10,Addres_2=1,Addres_3=168,Addres_4=192;

int main(void)

{

Stm32_Clock_Init(9);

//usart_init(72,9600);

USART3_Init(36,9600);

USART2_Init(36,9600);

delay_init(72);

LED_Init();

LCD12864_InitPort();

LCD12864_Init();//系统时钟设置

// 串口初始化为 9600

//延时初始化

// 初始化与 LED 连接的硬件接口

//初始化 LCD

//KEY_Init();

RTC_Init();

// usmart_(72);

EXTIX_Init();

while(tapdev_init())

{

//初始化按键

// 初始化 RTC

//初始化 USMART

//初始化 ENC28J60 错误

LCD_ShowString(3,0,"28J60 InitError!");

delay_ms(200);

LCD12864_Clr();// 清除之前显示

};

uip_init();

uip_sethostaddr(ipaddr);

uip_ipaddr(ipaddr, 192,168,1,1);

uip_setdraddr(ipaddr);

uip_ipaddr(ipaddr, 255,255,254,0);

uip_setnetmask(ipaddr);

//监听 1200 端口 ,用于 TCP Server

//监听 80 端口 ,用于 Web Server

//uIP 初始化

uip_ipaddr(ipaddr, 192,168,1,10); //设置本地设置 IP 地址

〃设置网关IP地址(其实就是你路由器的IP地址)

//设置网络掩码

uip_listen(HTONS(1200));

uip_listen(HTONS(80));

tcp_client_reconnect();

while (1)

{ Display_Time();

uip_polling();

II尝试连接到 TCP Server端,用于TCP Client

//处理 uip 事件,必须插入到用户程序的循环体中

II key=KEY_Scan();

if(tcp_client_tsta!=tcp_client_sta)IITCP Client 状态改变

{

if(tcp_client_sta&(1<<7))

{

LCD_ShowString(3,0," 接收数据 :");

disp_IP();

}

else

{ LCD_ShowString(3,0," 已断开 !

disp_IP();

}

");

if(tcp_clie nt_sta&(1<<6))

{

〃收到新数据

IILCD12864_Clr(); II 清除之前显示

received_date(tcp_client_databuf);

tcp_client_sta&=~(1<<6);

}

tcp_client_tsta=tcp_client_sta;

}

delay_ms(1);

usart3_Receive_Process();

} }

//uip 事件处理函数 //必须将该函数插入用户主循环 ,循环调用 .

void uip_polling(void)

{

u8 i;

static struct timer periodic_timer, arp_timer;

static u8 timer_ok=0;

if(timer_ok==0)// 仅初始化一次

{

timer_ok = 1;

timer_set(&periodic_timer,CLOCK_SECOND/2); //创建 1 个 0.5 秒的定时器

timer_set(&arp_timer,CLOCK_SECOND*10);

}

// 创建 1 个 10 秒的定时器

uip_len=tapdev_read(); //从网络设备读取一个

if(uip_len>0)

{

IP 包 ,得到数据长度 .uip_len 在 uip.c 中定

//有数据

//处理 IP 数据包 (只有校验通过的 IP 包才会被接收 ) if(BUF->type ==

htons(UIP_ETHTYPE_IP))// 是否是 IP 包 ?

{

uip_arp_ipin();

uip_input();

// 去除以太网头结构,更新

//IP 包处理

ARP 表

//当上面的函数执行后,如果需要发送数据,则全局变量 uip_len > 0 //需要发送的数据在 uip_buf, 长度是 uip_len (这是 2 个全局变量 ) if(uip_len>0)// 需要回应数据

{

uip_arp_out();// 加以太网头结构,在主动连接时可能要构造 ARP 请求

tapdev_se nd();〃发送数据到以太网

}

}else if (BUF->type==htons(UIP_ETHTYPE_ARP))〃 处理 arp 报文,是否是 ARP 请求

包?

{

uip_arp_arpin();

//当上面的函数执行后,如果需要发送数据,则全局变量 uip_len>0 //需要发送的数据在 uip_buf, 长度是 uip_len( 这是 2 个全局变量 ) if(uip_len>O)tapdev_send();〃 需要发送数据,则通过 tapdev_send 发送

}

}else if(timer_expired(&periodic_timer)) //0.5 秒定时器超时

{timer_reset(&periodic_timer); //复位 0.5 秒定时器

//轮流处理每个 TCP连接,UIP_CONNS缺省是40个

for(i=0;i

{

uip_periodic(i); //处理 TCP 通信事件 //当上面的函数执行后,如果需要发送数据,则全局变量 uip_len>0 //需要发送的数据在 uip_buf, 长度是 uip_len (这是 2 个全局变量 ) if(uip_len>0)

{

uip_arp_out();// 加以太网头结构,在主动连接时可能要构造 ARP 请求

tapdev_se nd();〃发送数据到以太网

}

}

#if UIP_UDP //UIP_UDP

//轮流处理每个 UDP 连接 , UIP_UDP_CONNS 缺省是 10 个

for(i=0;i

{

uip_udp_periodic(i); //处理 UDP 通信事件

//当上面的函数执行后,如果需要发送数据,则全局变量 uip_len>0 //需要发送的数据在 uip_buf, 长度是 uip_len ( 这是 2 个全局变量 ) if(uip_len > 0)

{

uip_arp_out();〃加以太网头结构,在主动连接时可能要构造

tapdev_se nd();〃发送数据到以太网

}

}

ARP请求

#endif

//每隔 10 秒调用 1次 ARP 定时器函数 用于定期 ARP 处理 ,ARP 表 10秒更新一次,

旧的条目会被抛弃

if(timer_expired(&arp_timer))

{

timer_reset(&arp_timer); uip_arp_timer();

}

}

}

void Display_Time(void)

{ if(t!=)

{ t=;

LCD_ShowString(1,5," 星期 ");

LCD_ShowString(0,3,"20");

LCD_Shownum(0,4,(timer.w_year%100));

LCD12684_Wdat(0x2d);

LCD_Shownum1(timer.w_month);

LCD12684_Wdat(0x2d);

LCD_Shownum1(timer.w_date);

switch()

{

case 0:LCD_ShowString(1,7," 日 ");break;

case 1:LCD_ShowString(1,7," 一 ");break;

case 2:LCD_ShowString(1,7," 二 ");break;

case 3:LCD_ShowString(1,7," 三 ");break;

case 4:LCD_ShowString(1,7," 四 ");break; case 5:LCD_ShowString(1,7," 五

");break; case 6:LCD_ShowString(1,7," 六 ");break;

}

LCD_Shownum(1,0,);

LCD12684_Wdat(0x3a);

LCD_Shownum1();

LCD12684_Wdat(0x3a);

LCD_Shownum1();

}

}

void received_date(u8 *str)

{ u8 len;

len=(u8)strlen(str);

switch(len)

{

case 13: Addres_4= (u8)Process_date(0,(str[0]-0x30),str[1],str[2]); Addres_3=

(u8)Process_date(0,(str[4]-0x30),str[5],str[6]); Addres_2=(u8)Process_date(0,0,str[8],str[9]);

Addres_1=(u8)Process_date(0,0,str[11],str[12]); uip_ipaddr(ipaddr,

Addres_4,Addres_3,Addres_2,Addres_1); 设置 IP 地址

uip_sethostaddr(ipaddr); tcp_client_reconnect();

disp_IP(); break;

case 19:RTC->CRH&=~(0X01);

while(!(RTC->CRL&(1<<5))); //等待 RTC 寄存器操作完成

timer.w_year=(s16)Process_date(str[0]-0x30,str[1]-0x30,str[2],str[3]);

timer.w_month=(s8)Process_date(0,0,str[5],str[6]);

timer.w_date=(s8)Process_date(0,0,str[8],str[9]);

=(s8)Process_date(0,0,str[11],str[12]);

=(s8)Process_date(0,0,str[14],str[15]);

=(s8)Process_date(0,0,str[17],str[18]);

RTC_Set(timer.w_year,timer.w_month,timer.w_date,,,);

RTC->CRH|=0X01;

while(!(RTC->CRL&(1<<5))); // 等待 RTC 寄存器操作完成 break;

case 6:

case 7:

case 8:

case 9:

// 设 置 本 地

// 设置时间

case 10 :

case 11 : LCD_ShowString(3,5,str);

Speech(str);break;

default : break;

}

}

u16 Process_date(u8 q,u8 b,u8 s,u8 g)

{

u16 temp; temp=q*1000+b*100+(s-0x30)*10+(g-0x30); return temp ;

}

HARDW ARE 文件夹下 rtc。 C 文件

#include "sys.h"

#include "rtc.h"

#include "delay.h"

#include "usart.h"

////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //Mini STM32 开发板

//RTC 实时时钟 驱动代码

//正点原子 @ALIENTEK

//技术论坛 :

//修改日期 :2010/12/30

//版本: V1.1

//版权所有,盗版必究。

//Copyright(C) 正点原子 2009-2019

//All rights reserved

//*****************************************************************************

//V1.1 修改说明

//修改了 RTC_Init 函数分频设置无效的 bug

//修改了 RTC_Get 函数的一个 bug //////////////////////////////////////////////////////////////////////////////////

//Mini STM32 开发板

//RTC 实时时钟 驱动代码

//正点原子 @ALIENTEK

//2010/6/6 tm timer;// 时钟结构体 //实时时钟配置 //初始化 RTC 时钟 ,同时检测时钟是否工作正常

//BKP->DR1 用于保存是否第一次配置的设置 //返回 0:正常

//其他 :错误代码

u8 RTC_Init(void)

{

//检查是不是第一次配置时钟

u8 temp=0;

if(BKP->DR1!=0X5050)// 第一次配置

RCC->APB1ENR|=1<<28;

RCC->APB1ENR|=1<<27;

PWR->CR|=1<<8;

RCC->BDCR|=1<<16;

RCC->BDCR&=~(1<<16);

RCC->BDCR|=1<<0;

//使能备份时钟 //取消备份区写保护 //备份区域软复位 //备份区域软复位结束 //开启外部低速振荡器//使能电源时钟

while((!(RCC->BDCR&0X02))&&temp<250)// 等待外部时钟就绪

temp++; delay_ms(10);

};

if(temp>=250)return 1;// 初始化时钟失败 ,晶振有问题

RCC->BDCR|=1<<8; //LSI 作为 RTC 时钟

RCC->BDCR|=1<<15;//RTC 时钟使能

while(!(RTC->CRL&(1<<5)));// 等待 RTC 寄存器操作完成

while(!(RTC->CRL&(1<<3)));// 等待 RTC 寄存器同步

RTC->CRH|=0X01; //允许秒中断

while(!(RTC->CRL&(1<<5)));//

RTC->CRL|=1<<4;

RTC->PRLH=0X0000;

RTC->PRLL=32767;

值: 32767

等待 RTC 寄存器操作完成 //允许配置

// 时钟周期设置 (有待观察 ,看是否跑慢了 ?)理论

Auto_Time_Set();

//设置时间 //配置更新

//RTC_Set(2009,12,2,10,0,55);

// 等待 RTC 寄存器操作完成

RTC->CRL&=~(1<<4);

while(!(RTC->CRL&(1<<5)));

BKP->DR1=0X5050;

//BKP_Write(1,0X5050);;// 在寄存器 1 标记已经开启了

//printf("FIRST TIMEn");

}else// 系统继续计时

{

while(!(RTC->CRL&(1<<3)));//

等待 RTC 寄存器同步

RTC->CRH|=0x01;

//printf("OKn");

}

//允许秒中断

while(!(RTC->CRL&(1<<5)));//

等待 RTC 寄存器操作完成

MY_NVIC_Init(0,0,RTC_IRQChannel,2);//RTC,G2,P2,S2. 优先级最低 RTC_Get();// 更新时间

return 0; //ok

}

//RTC 中断服务函数

//const u8* Week[2][7]=

//{

//{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"},

//{" 日","一"," 二","三","四","五","六"}

//};

//RTC 时钟中断

//每秒触发一次

void RTC_IRQHandler(void)

{

if(RTC->CRL&0x0001)// 秒钟中断

{

RTC_Get();// 更新时间

//printf("CRL:%dn",RTC->CRL);

}

if(RTC->CRL&0x0002)// 闹钟中断

//printf("Alarm!n");

RTC->CRL&=~(0x0002);// 清闹钟中断

//闹钟处理

}

RTC->CRL&=0X0FFA; // 清除溢出,秒钟中断标志

while(!(RTC->CRL&(1<<5)));// 等待 RTC 寄存器操作完成

}

//判断是否是闰年函数

1 2 3 4 5 6 7 8 9 10 11 12

31 29 31 30 31 30 31 31 30 31 30 31

//月份

//闰年

//非闰年 31 28 31 30 31 30 31 31 30 31 30 31

//输入 :年份

//输出 :该年份是不是闰年 .1,是 .0,不是

u8 Is_Leap_Year(u16 year)

{

if(year%4==0) // 必须能被 4 整除

{

if(year%100==0)

{

if(year%400==0)return 1;// 如果以 00 结尾 ,还要能被 400 整除

else return 0;

}else return 1;

}else return 0;

}

//设置时钟 //把输入的时钟转换为秒钟 //以 1970 年 1 月 1

日为基准 //1970~2099 年为合法年份 //返回值 :0,成功 ;其他 :错误代码 . //月份数据表 u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; // 月修正数据表 //平年的月份日期表

const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};

u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)

{

u16 t;

u32 seccount=0; if(syear<1970||syear>2099)return 1;

for(t=1970;t

{

if(Is_Leap_Year(t))seccount+=31622400;// 闰年的秒钟数

else seccount+=31536000; // 平年的秒钟数

}

smon-=1;

for(t=0;t

{//把前面月份的秒钟数相加

seccount+=(u32)mon_table[t]*86400;// 月份秒钟数相加

if(Is_Leap_Year(syear)&&t==1)seccount+=86400;// 闰年 2 月份增加一天的秒钟数

}

seccount+=(u32)(sday-1)*86400;// 把前面日期的秒钟数相加

seccount+=(u32)hour*3600;// 小时秒钟数 seccount+=(u32)min*60; // 分钟秒钟数

seccou nt+=sec;〃最后的秒钟加上去

//设置时钟

RCC->APB1ENR|=1<<28; // 使能电源时钟

RCC->APB1ENR|=1<<27; // 使能备份时钟

PWR->CR|=1<<8; //取消备份区写保护 //上面三步是必须的 !

RTC->CRL|=1<<4; //允许配置

RTC->CNTL=seccount&0xffff;

RTC->CNTH=seccount>>16;

RTC->CRL&=~(1<<4);// 配置更新 while(!(RTC->CRL&(1<<5)));// 等待 RTC 寄存器操作完成 return 0;

}

//得到当前的时间 //返回值 :0,成功;其他:错误代码 . u8 RTC_Get(void)

static u16 daycnt=0;

u32 timecount=0;

u32 temp=0;

u16 temp1=0;

timecount=RTC->CNTH;// 得到计数器中的值 (秒钟数 )

timecount<<=16;

timecount+=RTC->CNTL;

temp=timecount/86400;

{

{

//得到天数 (秒钟数对应的 )

if(daycnt!=temp)// 超过一天了

daycnt=temp;

temp1=1970; //从 1970 年开始 while(temp>=365)

{

if(Is_Leap_Year(temp1))// 是闰年

{

if(temp>=366)temp-=366;// 闰年的秒钟数

else break;

}

else temp-=365;

temp1++;

}

//平年

timer.w_year=temp1;// 得到年份 temp1=0;

while(temp>=28)// 超过了一个月

{

if(Is_Leap_Year(timer.w_year)&&temp1==1)// 当年是不是闰年 /2 月份

{

if(temp>=29)temp-=29;// 闰年的秒钟数

else break;

}

else

{

if(temp>=mon_table[temp1])temp-=mon_table[temp1];// 平年 else break;

}

temp1++;

}

timer.w_month=temp1+1;// 得到月份 timer.w_date=temp+1; //得到日期

}

temp=timecount%86400;

=temp/3600;

//得到秒钟数

// 小时

=(temp%3600)/60; // 分钟 =(temp%3600)%60; // 秒钟

=RTC_Get_Week(timer.w_year,timer.w_month,timer.w_date);// 获取星期

return 0;

}

//获得现在是星期几

//功能描述 :输入公历日期得到星期 ( 只允许 1901-2099 年 ) //输入参数:公历年月日

//返回值:星期号

u8 RTC_Get_Week(u16 year,u8 month,u8 day)

{

u16 temp2;

u8 yearH,yearL;

yearH=year/100; yearL=year%100;

// 如果为 21 世纪 ,年份数加 100

if (yearH>19)yearL+=100;

// 所过闰年数只算 1900 年之后的 temp2=yearL+yearL/4;

temp2=temp2%7; temp2=temp2+day+table_week[month-1];

if (yearL%4==0&&month<3)temp2--; return(temp2%7);

}

//比较两个字符串指定长度的内容是否相等

//参数:s1,s2要比较的两个字符串;len,比较长度

//返回值 :1,相等;0,不相等

u8 str_cmpx(u8*s1,u8*s2,u8 len)

{

u8 i; for(i=0;i

}

extern const u8 *COMPILED_DA TE

;//获得编译日期 extern const u8

*COMPILED_TIME;// 获得编译时间 const

Month_Tab[12][3]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };

//自动设置时间为编译器时间

void Auto_Time_Set(void)

{

u8 temp[3];

u8 i;

u8 mon,date;

u16 year;

u8 sec,min,hour;

for(i=0;i<3;i++)temp[i]=COMPILED_DATE[i]; for(i=0;i<12;i++)if(str_cmpx((u8*)Month_Tab[i],temp,3))break;

mon=i+1;// 得到月份

if(COMPILED_DATE[4]==' ')date=COMPILED_DA TE[5]-'0';

else date=10*(COMPILED_DA TE[4]-'0')+COMPILED_DATE[5]-'0';

year=1000*(COMPILED_DATE[7]-'0')+100*(COMPILED_DATE[8]-'0')+10*(COMPILED

_DATE[9]-'0')+COMPILED_DATE[10]-'0';

hour=10*(COMPILED_TIME[0]-'0')+COMPILED_TIME[1]-'0';

min=10*(COMPILED_TIME[3]-'0')+COMPILED_TIME[4]-'0';

sec=10*(COMPILED_TIME[6]-'0')+COMPILED_TIME[7]-'0';

RTC_Set(year,mon,date,hour,min,sec)

//printf("%d-%d-%d %d:%d:%dn",year,mon,date,hour,min,sec);}

u8

Hardware 文件夹下 exit。 C

#include "exti.h"

#include "led.h"

#include "key.h"

#include "delay.h"

#include "usart.h"

#include "12864.h"

#include "rtc.h" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //Mini STM32 开发板

//外部中断 驱动代码

//正点原子 @ALIENTEK

//技术论坛 :

//修改日期 :2010/12/01

//版本: V1.0 //版权所有,盗版必究。

//Copyright(C) 正点原子 2009-2019

//All rights reserved //////////////////////////////////////////////////////////////////////////////////

//外部中断 0 服务程序

void EXTI0_IRQHandler(void)

{

delay_ms(100);// 消抖 if(KEY2==1) // 按键 2

{ count++;

if(count<7)

{ while(!(RTC->CRL&(1<<3)));// 等待 RTC 寄存器同步 RTC->CRH&=~(0X01); //允许秒中断

while(!(RTC->CRL&(1<<5)));// 等待 RTC 寄存器操作完成

}

switch(count)

{ case 1 : LCD_ShowString(2,4," 设置秒 ");break; case 2 : LCD_ShowString(2,4," 设置分

");break;

case 3 : LCD_ShowString(2,4," 设置时 ");break;

case 4 : LCD_ShowString(2,4," 设置日 ");break;

case 5 : LCD_ShowString(2,4," 设置月 ");break;

case 6 : LCD_ShowString(2,4," 设置年 ");break; case 7

{ RTC_Set(timer.w_year,timer.w_month,timer.w_date,,,);

while(!(RTC->CRL&(1<<3)));// 等待 RTC 寄存器同步

RTC->CRH|=0X01; // 允许秒中断 while(!(RTC->CRL&(1<<5)));// 等待 RTC 寄存器操作完成

LCD_ShowString(2,4," 设 置

");LCD_ShowString(3,0,">");disp_IP(); }break;

case 8 : LCD_ShowString(3,0,">>");break;

case 9 : LCD_ShowString(3,0,">>>");break;

case 10 : LCD_ShowString(3,0,">>>>");break;

IP

case 11 : count=0;LCD_ShowString(3,0," ");LCD_ShowString(2,4, ");break;

}

}

EXTI->PR=1<<0; // 清除 LINE0 上的中断标志位

}

//外部中断 15~10 服务程序

void EXTI15_10_IRQHandler(void)

{

delay_ms(100);

if(KEY0==0)

{ LED1=!LED1;

switch(count)

{

// 消抖

// 按键 0

case 1

--;if(==0)=59;LCD_Shownum(1,4,);LCD_ShowString(2,7,"-") ;break;

case 2

--;if(==0)=59;LCD_Shownum(1,2,);LCD_ShowString(2,7, "-");break;

case 3

--;if(==0)=12;LCD_Shownum(1,0,);LCD_ShowString(2,

7,"-");break;

case 4

timer.w_date--;if(timer.w_date==0)timer.w_date=31;LCD_Shownum(0,4,timer.w_date);LCD_Sho

wString(2,7,"-");break;

case 5

timer.w_month--;if(timer.w_month==0)timer.w_month=12;LCD_Shownum(0,2,timer.w_month);

LCD_ShowString(2,7,"-");break;

case 6

timer.w_year--;if(timer.w_year==0)timer.w_year=2099;LCD_Shownum(0,0,(timer.w_year%100)) ;LCD_ShowString(2,7,"-");break;

case 7 : Addres_1--;if(Addres_1==0) Addres_1=99;disp_IP();break;

case 8 : Addres_2--;if(Addres_2==0) Addres_2=9;disp_IP();break;

case 9 : Addres_3--;if(Addres_3==0)Addres_3=200;disp_IP();break;

case 10 : Addres_4--;if(Addres_4==0)Addres_4=200;disp_IP();break;

}

}else if(KEY1==0)// 按键 1

{LED0=!LED0; switch(count)

{

case 1

++;if(==60)=0;LCD_Shownum(1,4,);LCD_ShowString(2,7,"+

");break;

case 2

++;if(==60)=0;LCD_Shownum(1,2,);LCD_ShowString(2,7 ,"+"); break;

case 3

++;if(==12)=0;LCD_Shownum(1,0,);LCD_ShowString( 2,7,"+");break;

case 4

timer.w_date++;if(timer.w_date==32)timer.w_date=0;LCD_Shownum(0,4,timer.w_date);LCD_Sh

owString(2,7,"+");break;

case 5

timer.w_month++;if(timer.w_month==32)timer.w_month=0;LCD_Shownum(0,2,timer.w_month);

LCD_ShowString(2,7,"+"); break;

case 6

timer.w_year++;if(timer.w_year==2099)timer.w_year=2014;LCD_Shownum(0,0,(timer.w_year%

100));LCD_ShowString(2,7,"+");break;

case 7 : Addres_1++;if(Addres_1==100)Addres_1=0;disp_IP();break; case 8

Addres_2++;if(Addres_2==10)Addres_2=0;disp_IP();break;

case 9 : Addres_3++;if(Addres_3==1000)Addres_3=0;disp_IP();break;

case 10: Addres_4++;if(Addres_4==1000)Addres_4=0;disp_IP();break;

}

}

EXTI->PR=1<<13; // 清除 LINE13 上的中断标志位

EXTI->PR=1<<15; // 清除 LINE15 上的中断标志位

}

//外部中断初始化程序

//初始化 PA0,PA13,PA15 为中断输入 .

void EXTIX_Init(void)

{

RCC->APB2ENR|=1<<2; //使能 PORTA 时钟

JTAG_Set(JTAG_SWD_DISABLE);// 关闭 JTAG 和 SWD

GPIOA->CRL&=0XFFFFFFF0;//PA0 设置成输入 GPIOA->CRL|=0X00000008;

GPIOA->CRH&=0X0F0FFFFF;//PA13,15 设置成输入 GPIOA->CRH|=0X80800000;

GPIOA->ODR|=1<<13; //PA13 上拉 ,PA0 默认下拉

GPIOA->ODR|=1<<15; //PA15 上拉

Ex_NVIC_Config(GPIO_A,0,RTIR); // 上升沿触发

Ex_NVIC_Config(GPIO_A,13,FTIR);// 下降沿触发

Ex_NVIC_Config(GPIO_A,15,FTIR);// 下降沿触发

MY_NVIC_Init(2,2,EXTI0_IRQChannel,2); //抢占 2,子优先级 2,组 2

MY_NVIC_Init(2,1,EXTI15_10_IRQChannel,2);// 抢占 2,子优先级 1,组 2

}

void

disp_IP(void)

{

LCD12864_Pos(3,2); LCD12684_Wdat(Addres_4/100+0x30);

LCD12684_Wdat((Addres_4%100)/10+0x30);

LCD12684_Wdat((Addres_4%100)%10+0x30); LCD12684_Wdat(0x2e);

:

LCD12864_Pos(3,4); LCD12684_Wdat(Addres_3/100+0x30);

LCD12684_Wdat((Addres_3%100)/10+0x30);

LCD12684_Wdat((Addres_3%100)%10+0x30); LCD12684_Wdat(0x2e);

LCD12864_Pos(3,6); LCD12684_Wdat(Addres_2+0x30); LCD12684_Wdat(0x2e);

LCD12864_Pos(3,7);

LCD12684_Wdat(Addres_1/10+0x30); LCD12684_Wdat(Addres_1%10+0x30);

其他文件用原子 rtc 时钟的程序就行

}