历史上的今天
今天是:2025年04月22日(星期二)
2018年04月22日 | STM32学习笔记(串口、IAP)
2018-04-22 来源:eefocus
串口:
一. USART_ITConfig(USART1, USART_IT_TXE, ENABLE):
只要发送寄存器为空,就会一直有中断,因此,要是不发送数据时,把发送中断关闭,只在开始发送时,才打开。
二.
以下是字符发送的配置过程,注意第6点,在设置USART_CR1中的TE位时,会发送一个空闲帧作为第一次数据发送,所以即便你执行了USART_ClearFlag(USART1, USART_FLAG_TC); (这个函数肯定在空闲帧数据发送完成前执行),所以当空闲帧发送完后,就进入发送完成中断。
配置步骤:
1. 通过在USART_CR1寄存器上置位UE位来激活USART
2. 编程USART_CR1的M位来定义字长。
3. 在USART_CR2中编程停止位的位数。
4. 如果采用多缓冲器通信,配置USART_CR3中的DMA使能位(DMAT)。按多缓冲器通信中
的描述配置DMA寄存器。
5. 利用USART_BRR寄存器选择要求的波特率。
6. 设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。
7. 把要发送的数据写进USART_DR寄存器(此动作清除TXE位)。在只有一个缓冲器的情况
下,对每个待发送的数据重复步骤7。
8. 在USART_DR寄存器中写入最后一个数据字后,要等待TC=1,它表示最后一个数据帧的
传输结束。当需要关闭USART或需要进入停机模式之前,需要确认传输结束,避免破坏
最后一次传输。
解决的办法:
方法一
在执行USART_ITConfig(USART1,USART_IT_TC, ENABLE); 之前,
先延时一段时间,基本上比一个字符发送的时间长一点就可以了,然后再执行
USART_ClearFlag(USART1, USART_FLAG_TC);
方法二:
在执行USART_ITConfig(USART1,USART_IT_TC, ENABLE); 之前,
USART_ClearFlag(USART1, USART_FLAG_TC);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)
{
; //等待空闲帧发送完成后 再清零发送标志
}
USART_ClearFlag(USART1,USART_FLAG_TC);
三.
TXE:发送缓冲器空闲标志
RXNE:接收缓冲区非空
IAP:
一.
问:
这几天在折腾STM32的IAP,参考了两个例程,一个AN2557,然后一个就是标准外设库内的flash例程
总结IAP:
1.Flash解锁 FLASH_Unlock();
2.清除Flash所有的未完成的标志位 FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
3.根据文件大小擦除Flash
for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
{
FLASHStatus = FLASH_ErasePage(StartAddr + (FLASH_PAGE_SIZE * EraseCounter));
}
4.编程Flash
while((Address < EndAddr) && (FLASHStatus == FLASH_COMPLETE))
{
FLASHStatus = FLASH_ProgramWord(Address, Data);
Address = Address + 4;
}
5.检验编入数据的正确性
while((Address < EndAddr) && (MemoryProgramStatus != FAILED))
{
if((*(__IO uint32_t*) Address) != Data)
{
MemoryProgramStatus = FAILED;
}
Address += 4;
}
在以上几步中,如果上面没有问题的话,提出下面几个疑问
1.假如我的应用程序的地址应该从0x8003000开始,那么我把后面的页全部擦除是否可以? 虽然我的程序可能只占到0x8003000-0x8005000 那么这之后的页是否也可以一并擦除?
2.在编程的时候有个很小的问题,因我的数据都是以字节(byte)的形式储存的,在写的时候因为只能以半字(16位)或一个字(32位)的方式编程,那么如果我的bin
文件的最后一个字节并不够两个字节,怎么办?举例:我的bin文件的大小是501个字节(8位),我的写入方法是这样的:
data[501] = {X,X,X...}//应用程序bin文件内容
temp = data[0];
temp = temp << 8;
temp |= data[1];
temp = temp << 8;
temp |= data[2];
teme = temp << 8;
teme |= data[3];//待写入得数据
FLASHStatus = FLASH_ProgramWord(Address, temp);//写入flash
如果像这样的话,那么不能被4整除的那一个字节怎么办?
3.IAP程序中有一处一直很迷惑,不能理解
/* Test if user code is programmed starting from address "ApplicationAddress" */
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
{ /* Jump to user application */
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
}
程序的整体是要跳出IAP引导区跳到应用程序区.那么这句判断的依据是什么?if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
倘若我今天的程序是重0x8003000处开始,那么明天我升级一个程序,他的开始是0x80080000呢?这里需要改吗?
0x2FFE0000 0x20000000 这两个数我在AN2557的例子代码里反复寻找,并没有哪里出现,那么又是怎么跟用户的应用程序关联的呢?
还有如果将上面的例子直接这样更改,是否可以达到跳转到应用程序区的目的呢?
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); //这里为何要+4 ?+了4不就跳过出应用程序的入口了吗?
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
4.关于Flash的写保护问题,在3.0标准外设库中Flash还有另外一个例子,就是关于保护的
无疑flash的保护是对程序的一个安全保障,但目前我买的新片子(未进行过任何保护方面的操作)中,是否不需要考虑这些问题,直接擦除,然后编程即可?
5.有什么理由要“今天的程序是重0x8003000处开始,明天又升级一个程序,他的开始是呢”?第1没有必要,第2是自寻烦恼。开始地址是你自己定的,为什么要自己为难自己?
这个问题怪我没说清楚,其实我是想说,我现在的引导区这样定义的#ApplicationAddress 0x80030000我只能启动起始地址在0x08003000 处的应用程序,那么这段代码是可以成功启动的(我验证过):
/* Test if user code is programmed starting from address "ApplicationAddress" */
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
{ /* Jump to user application */
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
}
那如果我现在想引导启动地址在0x80080000的应用程序,是否只要更改#ApplicationAddress 0x80080000这句就好?上面那串代码就不需要更改了吧?
我还是想理解了上面的那串代码到底是为什么?希望香版能仔细帮我解释下,(当我白痴好了,呵呵)!
答:
1. 可以,只要不影响功能就行
2. 比较好的解决方法,先读一页出来到RAM,擦掉这一页Flash,在RAM中修改相应的Bytes,再将整页写回去。 一般的解决方法,后面不足一个WORD/DWORD的补0xff或0x00,补齐一个WORD或DWORD
3. ApplicationAddress对应着你的应用程序"stm32f10x_vector.c"这个文件中的__vector_table
*(__IO uint32_t*)ApplicationAddress 与 __vector_table[0]是一样的
*(__IO uint32_t*) (ApplicationAddress + 4) 与 __vector_table[1]是一样的
__vector_table[0]是应用程序栈的顶
__vector_table[1]是应用程序的启动地址
这里有讨论过
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=1600156&bbs_page_no=3&bbs_id=3020
(X & 0x2FFE0000 ) == 0x20000000 意思是说X是不是在0x20000000与0x2001FFFF之间,即栈顶是不是在以0x20000000开始的128K
的范围内,这里便是STM32的RAM区域,虽然现在最大的只有64k
如果你的bootloader只能启动0x08003000的应用程序,那么你写一个起始地址在0x08008000的程序他将不能启动
你要写一个在0x080003000的启动程序来启动0x08008000的应用程序,或者把0x08008000前八字节的内容放到0x08003000中
4. 是的,买回来的可以直接写,出厂时芯片的Flash都没有设置保护。
5.
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
==================================================================================
判断用户是否已经下载程序,因为正常情况下此地址是栈地址。若没有这一句的话,即使没有下载程序也会进入而导致跑飞。
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
====================================================================================
获取程序地址,并设置栈指针,然后跳转到用户下载的程序中运行。
二.
msr msp, r0 将堆栈地址保存到主堆栈指针msp中
触发SVC软中断,由vPortSVCHandler()完成第一个任务的具体切换工作
史海拾趣
|
在wince平台下,我们通过调用IDirectDrawVideoPort中的StartVideo函数,但是StartVideo调用不成功,不知有那位大侠帮小弟分析一个原因或可能出错的地方。以下是关于StartVideo的一些代码: memset(&g_vpInfo,0,sizeof(g_vpInfo)); //add ...… 查看全部问答> |
|
发现一个很奇怪的问题: S3C6410+WinCE6.0的系统,两个中断同一时刻来的时候,就出现丢数的现象。 详细情况是这样:做磁卡的驱动,有两个磁道:每个磁道有一个时钟线、一个数据线。 ...… 查看全部问答> |
|
我现在把framebuffer设置为1280X720, 然后我在写buffer的时候,写进去的是一张:720X480的图片 这样的画这个图片只会显示在左上脚,我要如何设置才能让这个图片全屏显示?谢谢...… 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 09:30 编辑 如标题,这几个类型的技术问题在电子工程师技术交流QQ群应该可以讨论得起来。 QQ群号:12425841 … 查看全部问答> |
|
[求助]请问6720与SRAM的接口问题[已解决 附接线方法] 6720接STC的256*16 SRAM,一上电SRAM就发热,9V下总电流100多mA 硬件上没有短路,换了一片SRAM还是这样 如果让DSP处于复位状态SRAM就不会发热,电流也变的正常 请有经验的朋友帮忙看一下哪里有问题 我的接法是 SRAM D0~D15 ...… 查看全部问答> |
|
本帖最后由 dontium 于 2015-1-23 13:14 编辑 参考设计:Stellaris® AC 感应电机参考设计套件 型号:RDK-ACIM AC 感应电机概述 AC 感应电机 (ACIM) 是消费电子类应用和工业应用中最受欢迎的电机。此电机高度可靠,设计简单,其没 ...… 查看全部问答> |
|
前几天做了一个多功能Web查询系统,还不是很完善。功能基本可以全部实现,现在想和大家一起来分享一下!说明一点,本人上传的代码提供“技术支持、免费服务”大家可以去看看代码或者运行一下。。。。还要很多地方需要改进,希望大家多给建议。。。 ...… 查看全部问答> |




