分类目录归档:ARM

MDK 出现#68-D: integer conversion resulted in a change of sign(转)

在KeilARM的LPCARM,存在(1<<31)编译警告问题main.c(174): warning: #61-D: integer operation result is out of rangemain.c(174): warning: #68-D: integer conversion resulted in a change of sign由于编译器默认signed int即32位有符号整数类型,而1<<31实际为0x80000000,这样就有可能改写了符号位(最高位)依此类推,(2<<30),(3<<29)…等都会出现编译警告问题.解决办法为: ((unsigned int)1<<31),((unsigned int)2<<30),…

keil5 编译程序出现错误Error: L6411E: No compatible library exists with a definition of startup symbol __main(转)

Error: L6411E: No compatible library exists with a definition of startup symbol __main.
之前装过ADS,ADS与MDK冲突,依据网友提供的资料,最终的解决办法如下

在我的电脑点击属性>高级系统设置>高级>环境变量>在系统变量中>新建
(如果我的电脑只是快捷方式则属性中不会出现环境变量,需要在屏幕空白处右击,选择个性化,主题,找到桌面图标设置(系统不同,位置不一定一样,在个性化中可以找到),将计算机选项勾选即可)
变量名: ARMCC5LIB      
变量值:F:\Keil_v5\ARM\ARMCC\lib
(变量值是keil的安装目录,本人安装目录在F:\Keil_v5,剩下的目录是安装时系统自己建立,直接相同即可)
———————
作者:lnwechag
来源:CSDN
原文:https://blog.csdn.net/lnwechag/article/details/50760001
版权声明:本文为博主原创文章,转载请附上博文链接!

LPC1768 内部RTC程序

typedef struct{

uint8_t RTC_Sec;

uint8_t RTC_Min;

uint8_t RTC_Hour;

uint8_t RTC_Mday;

uint8_t RTC_Wday;

uint16_t RTC_Yday;

uint8_t RTC_Mon;

uint16_t RTC_Year;

}RTCTime;

RTCTime LocalTime;

void RTCStart(void)

{

LPC_RTC->CCR |= 0x01;

}

void RTCInit( void )

{

LPC_SC->PCONP |= CLKPWR_PCONP_PCRTC; //开启RTC电源

if(!(LPC_RTC->CCR & 0x01)) //如果时钟没使能,使能时钟,使能位在芯片复位时状态不会变化,不用每次上电都使能

{

LPC_RTC->ILR = 0;

LPC_RTC->AMR = 0xff;

LPC_RTC->CIIR = 0;

LPC_RTC->CCR = 0;

LocalTime.RTC_Year = 2019;

LocalTime.RTC_Mon = 1;

LocalTime.RTC_Mday = 1;

LocalTime.RTC_Wday = 2;

LocalTime.RTC_Hour = 0;

LocalTime.RTC_Min = 0;

LocalTime.RTC_Sec = 0;

RTCSetTime(&LocalTime);

RTCStart();

}

}

void RTC_Get_Time(RTCTime* Time)

{

Time->RTC_Year= LPC_RTC->YEAR ;

Time->RTC_Mon = LPC_RTC->MONTH;

Time->RTC_Yday = LPC_RTC->DOY;

Time->RTC_Wday = LPC_RTC->DOW;

Time->RTC_Mday = LPC_RTC->DOM;

Time->RTC_Hour = LPC_RTC->HOUR;

Time->RTC_Min = LPC_RTC->MIN;

Time->RTC_Sec = LPC_RTC->SEC;

}

void RTCSetTime(RTCTime* Time)

{

LPC_RTC->SEC = Time->RTC_Sec;

LPC_RTC->MIN = Time->RTC_Min;

LPC_RTC->HOUR = Time->RTC_Hour;

LPC_RTC->DOM = Time->RTC_Mday;

LPC_RTC->DOW = Time->RTC_Wday;

LPC_RTC->DOY = Time->RTC_Yday;

LPC_RTC->MONTH = Time->RTC_Mon;

LPC_RTC->YEAR = Time->RTC_Year;

}

LPC1768读写W25Q128程序

uint8_t W25QXX_Buf[4096];

GPIO设置

/*SPI pin set*/

PinCfg.Funcnum = PINSEL_FUNC_3;

PinCfg.Portnum = 0;

PinCfg.Pinmode = PINSEL_PINMODE_TRISTATE;

PinCfg.Pinnum = SPI_SCK;

PINSEL_ConfigPin(&PinCfg);

PinCfg.Pinnum = SPI_MOSI;

PINSEL_ConfigPin(&PinCfg);

PinCfg.Pinnum = SPI_MISO;

PINSEL_ConfigPin(&PinCfg);

PinCfg.Funcnum = PINSEL_FUNC_0;

PinCfg.Portnum = 0;

PinCfg.OpenDrain = PINSEL_PINMODE_NORMAL;

PinCfg.Pinnum = SPI_CS;

PINSEL_ConfigPin(&PinCfg);

GPIO_SetDir(0, (1<<SPI_CS), 1);

GPIO_SetValue(0, (1<<SPI_CS));

void Spi_Initial(void)

{

SPI_CFG_Type spi0;

spi0.CPHA = SPI_CPHA_FIRST;

spi0.CPOL = SPI_CPOL_LO;

spi0.ClockRate = 3125000; //spi_clk = 25000000,25000000/8=3125000,能使用的最高频率

spi0.DataOrder = SPI_DATA_MSB_FIRST;

spi0.Databit = SPI_DATABIT_8;

spi0.Mode = SPI_MASTER_MODE;

SPI_Init(LPC_SPI,&spi0);

}

uint8_t SPIF_POLLING(void)

{

uint8_t n = 0xff;

while (n–)

{

if (LPC_SPI->SPSR & 0x80)

return TRUE;

}

return FALSE;

}

继续阅读

TCP相关知识

1、 三次握手过程最后一个数据包丢失

当Client端收到Server的SYN+ACK应答后,其状态变为ESTABLISHED,并发送ACK包给Server,如果此时ACK在网络中丢失,那么Server端该TCP连接的状态为SYN_RECV,并且依次等待3秒,6秒,12秒后重新发送SYN+ACK包,以便Client重新发送ACK包。

如果重发指定次数后,仍然未收到ACK应答,那么一段时间后,Server自动关闭这个连接。但是Client认为这个连接已经建立,如果Client端向Server端写数据,Server端将以RST包响应,Client端方能感知到Server端的错误,从而断开连接。

2、 TCP状态变迁

客户端:CLOSED-SYN_SENT_ESTABLISED-FIN_WAIT_1-FIN_WAIT_2-TIME_WAIT-CLOSED

服务器端:CLOSED-LISTEN-SYN_RCVD-ESTABLISED-CLOSE_WAIT-LAST_ACK-CLOSED

3、 TCP协议RST标志

发送RST包关闭连接时,不必等待缓冲区的包都发出去,直接丢弃缓冲区的包,发送RST包。

接收端收到RST包后,也不必发送ACK包来确认。

四次握手不是关闭TCP连接的唯一方法,有时,如果主机需要尽快关闭连接(或连接超时,端口或主机不可达),RST包将被发送,由于RST包不是TCP连接中的必须部分,可以只发送RST包(即不带ACK标记),但在正常的TCP连接中RST包可以带ACK确认标记,RST包是可以不要收到对方确认的。

处于LISTEN状态的控制块只能响应SYN握手包,对非SYN握手包返回一个RST报文。

以太网帧结构

帧结构图:

clip_image002

前同步码和帧开始定界符:一个帧以7个字节的前导码和1个字节的帧开始符作为帧的开始。在线路上帧的这部分的位模式是10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101011。

MAC 目的地址:第三个字段是6字节(MAC地址占48位,如:FF,FF,FF,FF,FF),发送方的网卡(MAC)地址,用处是当网卡接收到一个数据帧时,首先会检查该帧的目的地址,是否与当前适配器的物理地址相同,如果相同则会进一步处理,不同则直接丢弃。

源MAC地址:发送端的MAC地址同样占6个字节。

类型:该字段在网络协议栈分解中及其重要,考虑当PDU(协议数据单元)来到某一层时,它需要将PDU交付给上层,而上层协议众多,所以在处理数据的时候,必须要一个字段标识我这个交付给谁。如,该字段为0x0800时,表示将有效载荷交付给IP协议,为0x0806交付给ARP,0X8035交付给RARP。

数据:数据也叫有效载荷,除过当前层协议需要使用的字段外,即需要交付给上层的数据,以太网帧数据长度规定最小为46字节,最大为1500字节,如果有不到46字节时,会用填充字节填充到最小长度。最大值也叫最大传输单元(MTU)。

帧检验序列FCS(使用CRC校验法):检测该帧是否出现差错。抓包时无法看到4字节校验值。

以太网规定以太网帧数据域部分最小为64字节(6字节目的MAC地址+6字节源MAC地址+2字节协议类型+最小46字节数据+4字节CRC校验),CRC校验抓包时无法看到。数据字段长度小于46字节时,MAC子层会在数据字段的后面填充以满足数据帧长度不小于64字节。由于填充数据由MAC子层负责,不同的抓包软件抓到的数据帧大小可能不同,比如一个TCP的ACK确认帧,有的抓包软件显示是54字节,有的显示是60字节。显示60字节的后面有填充数据段。

TCP连接过程解析

TCP客户端和服务器之间建立连接的过程称为3次握手过程。握手过程由客户端程序首先发起,整个过程要经历下面3个步骤:

1、客户端发送一个SYN标志置1的TCP报文段,报文段首部指明自己的端口号及期望连接的服务器端口好。在报文段中,客户端需要通告自己的初始序号ISN,除此之外,这个报文中还可以携带一些选项字段,例如最大报文段大小、窗口扩大因子,选项将客户端的一些连接属性通告给服务器。本报文段中ACK标志为0,因此它的确认号字段和通告窗口大小字段都会被视为无效。

00 E0 66 78 3A 84 E2 BB BC 41 4F 5A 08 00 45 00 00 3C 55 24 40 00 40 06 5B B6 C0 A8 03 77 C0 A8 05 1A E2 9E 1F 99 BE B1 91 02 00 00 00 00 A0 02 39 08 6F 08 00 00 02 04 05 B4 04 02 08 0A FF FF C4 26 00 00 00 00 01 03 03 02

00 E0 66 78 3A 84-以太网目的地址

E2 BB BC 41 4F 5A -以太网源地址

0800-帧类型,IP数据包

后面的为IP数据包

45-4表示使用IPV4版本,5*4=20字节,表示IP首部长度是20字节

00-TOS,描述当前IP数据报急需的服务类型,如最小延时,最大吞吐量,最高可靠性,最小费用等。路由器在转发数据报时,可以根据这个字段的值来为数据报选择最合理的路由路径。

003C-总长度,表示整个IP数据报(IP首部和数据区)的总字节数。总共60字节。

5524-16位标识字段,用于标识IP层发送出去的每一份IP数据报,每发送一份报文,该值加1,数据包被分片时,该字段会被复制到每一个分片中,在接收端,会使用这个字段值来组装所有分片为一个完整的数据报。

4000-3位标志字段和13位分片偏移量。高3位为010,第1位保留为今后使用,第2位是不分片位,此处为1,表示不分片。当该位为0时,IP层将在需要的时候对数据报进行分片处理。第3位表示更多分片位,此处为0,表示该分片是数据报的最后一个分片或者是唯一的分片,如果为1,说明该分片不是数据报的最后一个分片,后面还有分片的数据包。

13位偏移字段表示当前分片所携带的数据在整个数据报中的相对位置(以8字节为单位)。目的站必须收到从0偏移量到最高偏移量的所有分片,才能将分片重装成一个完整的数据报。每个分片在网络中断单独传输,它们到达终点的顺序可能会不相同,但在目的端,将按照分片的偏移量来顺序组织各个分片。

40-生存时间TTL。描述该IP数据报最多能被转发的次数,每经过一次转发,该值会减1,当该值为0时,路由器会丢弃掉分组,同时一个ICMP差错报文会被返回至源主机。

06-协议字段,1-表示ICMP协议,2-表示IGMP协议,6-表示TCP协议,17-表示UDP协议。

5BB6-首部校验和

C0A80377-源IP地址

C0A8051A -目的IP地址

继续阅读

LPC1768中断优先级设置

首先,说说中断优先级,所有中断均有一个优先级,

1、 更低的优先级数字代表着更高优先级

2、 除了RESET, Hard fault, NMI等系统级中断,其他所有中断优先级均可配置为”0~31″。

如果软件没有配置这些中断的优先级,那么所有中断的优先级默认为最高优先级”0″。此处 实例说明这个中断优先级的概念,假设三个外部中断”A,B,C”,”A,B”配置为”0″,”C”配置为”1″,

1、 如果三个中断同时产生,那么”A,B”中断优先”C”中断运行。

2、 “A,B”中断同时产生,谁更优先执行呢?那就根据中断向量表的排号,低的优先执行。

3、 若是”C”的中断正在运行,此时”A”的中断发生,那么”A”的中断会抢占”C”的执行权限,优先执行。

4、 若是”A”的中断正在运行,此时”B”的中断发生,那么新产生的”B”中断会进入等待状态,等 待”A”执行完毕再执行。

以上,只是单纯的判断优先级值来控制中断的顺序,为了增强中断的控制逻辑,ARM新增了优先级 组的概念。即相同的优先级等级可以分配在一组优先级内,在这一组优先级内再来定义次优先级,具 体是怎么一个概念呢?还是假设有四个中断”A,B,C,D”,”A,B,C”配置在优先级组”0″内,”A,B”中断配 置次优先级”0″,”C”配置为次优先级”1″,”D”则配置为优先级组”1″

1、 若”A,D”中断同时产生,则优先级高的”A”会优于”D”中断执行。

2、 若”A,C”中断同时产生,则优先级次优先级高的”A”会优先执行。

3、 若”A,B”中断同时产生,则根据中断向量表的位置,排号低的优先执行。

4、 若”D”正在执行中断,此时”A”中断来了,那么”A”中断会抢占”D”中断优先执行。因为”A”所 在的优先级组高于”D”。

5、 若”C”正在执行中断,此时”A”中断来了,那么”A”中断会等待”C”执行完毕再执行。因为属于同一优先级组。

ARM用了一个8位寄存器来定义优先级组和次优先级的概念。中间可以选择一个端点,高位表示有多少个主优先级,低位表示有多少个次优先级。而LPC1769只用了其中5位。

CM3每个中断都有一个优先级寄存器,对LPC1768来说,使用了高5位,低3位固定为0。

clip_image002

在CM3权威指南中

clip_image004

因为LPC1768低3位固定为0,所以优先级分组是从2-7.

clip_image006

最好选择分组2,B7-B3表达抢占优先级,没有子优先级位段。总共可以设置0-31个抢占优先级中断。抢占优先级可以实现中断嵌套。

UDP绑定IP_ADDR_ANY和固定IP的区别

在LWIP中,初始化一个UDP端口

struct udp_pcb *FirstUpcb;

如果绑定控制器的IP,要如下定义:

void First_UdpInit(void)

{

ip_addr_t local_ipaddr;

IP4_ADDR(&local_ipaddr,MyIP[0],MyIP[1],MyIP[2],MyIP[3]);

FirstUpcb = udp_new();

udp_bind(FirstUpcb,&local_ipaddr,FirstUdpport);

udp_recv(FirstUpcb,udp_callback,NULL);

}

MyIP[0],MyIP[1],MyIP[2],MyIP[3]为控制器的IP。

如果绑定IP_ADDR_ANY,如下定义:

void First_UdpInit(void)

{

FirstUpcb = udp_new();

udp_bind(FirstUpcb,IP_ADDR_ANY,FirstUdpport);

udp_recv(FirstUpcb,udp_callback,NULL);

}

当上位机发送一个UDP广播数据:

FF FF FF FF FF FF 00 E0 66 78 3A 84 08 00 45 00 00 2B 2F 01 00 00 40 11 85 FF C0 A8 05 1A FF FF FF FF 27 0E 27 0E 00 17 C5 EA 02 00 0B FF FF FF FF FF FF 31 55 00 FF 90 03

FF FF FF FF FF FF:目的MAC地址,表示是广播

00 E0 66 78 3A 84 :源MAC地址

08 00:帧类型,表示是IP包

以上是14字节以太网首部数据。

45 00 00 2B 2F 01 00 00 40 11 85 FF C0 A8 05 1A FF FF FF FF

是20字节IP首部,其中C0 A8 05 1A是源IP地址,FF FF FF FF是目的IP地址,这里表示是广播地址。

27 0E 27 0E 00 17 C5 EA

是UDP首部

02 00 0B FF FF FF FF FF FF 31 55 00 FF 90 03

是UDP数据。

如果控制器采用第一种方式初始化UDP端口,绑定自己的IP地址,那么不会接收这条UDP命令,因为这条命令的目的IP地址不等于本地IP地址。

如果控制器采用第二种方式初始化UDP端口,绑定IP_ADDR_ANY,控制器会接收到这条命令,UDP的回调函数会处理这条命令。

IP_ADDR_ANY的意思是,只要UDP数据的目的端口和UDP绑定的端口一样,UDP控制块就会处理这条数据,不管这条数据的目的IP是不是发送给本地IP。

LPC1768实现网络IAP

嵌入式系统一般都需要实现网络升级功能,方便维护。思路是把LPC1768的512K flash分为5部分:

Bootloader:0X0000 0000 – 0X0000 7FFF 32K 扇区0-7

应用程序:0X0001 0000 – 0X0004 7FFF 224K 扇区16-22

升级程序缓存区:0X0004 8000 – 0X0007 FFFF 224K 扇区23-29

扇区8用来保存升级数据包数量,每个数据包最大1024字节

扇区9用来放初始化标志,因为芯片出厂FLASH值都为0XFF,上电时读扇区9的值,如果不等于初始化标志,那么向扇区9写入初始化标志,并把扇区8保存数据包数量的地址清零。然后跳转到应用程序运行。

升级原理:应用程序运行时,接收到升级程序,把升级程序写入升级程序缓冲区,写完后把升级包的数量写入扇区8的起始位置,然后看门狗复位,开始执行Bootloader程序,升级程序先读取扇区9判断芯片是否初始化过,如果初始化标志正确,读扇区8保存的升级包数量,根据数据包数量读取升级程序缓存区的数据写到应用程序区,每次写一个数据包,即1024字节,写完后,把扇区8的起始位置4字节清零。最后跳转到应用程序,开始执行新的应用程序。升级完成。

LPC1768 FLASH地址分配如下:

clip_image002 继续阅读

第 1 页,共 3 页123