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 时钟的程序就行 }
发布评论