OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8516|回复: 68

改正以往的学习方法,按实验重新学习,在此发帖;分享自己做的笔记,也督促自己坚持下去。持之以恒!!!

[复制链接]

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
发表于 2016-10-22 22:06:21 | 显示全部楼层 |阅读模式
第一天点亮LED。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求让DS0DS1一起闪烁,周期为1S
I/O口的输入输出方式有八种,输出速度三种。
u     4种输入模式:
      输入浮空       //GPIO_Mode_IN_FLOATING
      输入上拉       //GPIO_Mode_IPU
      输入下拉       //GPIO_Mode_IPD
      模拟输入       //GPIO_Mode_AIN
u     4种输出模式:
     开漏输出        //GPIO_Mode_Out_OD
     开漏复用功能     //GPIO_Mode_AF_OD
     推挽式输出      //GPIO_Mode_Out_PP
     推挽式复用功能  //GPIO_Mode_AF_PP
浮空,顾名思义就是浮在空中,上面用绳子一拉就上去了,下面用绳子一拉就沉下去了.  
开漏,就等于输出口接了个NPN三极管,并且只接了e,b. c极 是开路的,你可以接一个      电阻到3.3V,也可以接一个电阻到5V,这样,在输出1的时候,就可以是5V电压,也可以是3.3V电压了.但是不接电阻上拉的时候,这个输出高就不能实现了.  
推挽,就是有推有拉,任何时候IO口的电平都是确定的,不需要外接上拉或者下拉电阻
(1) 浮空输入_IN_FLOATING ——浮空输入,可以做KEY识别,RX1
(2)带上拉输入_IPU——IO内部上拉电阻输入
(3)带下拉输入_IPD—— IO内部下拉电阻输入
(4) 模拟输入_AIN ——应用ADC模拟输入,或者低功耗下省电
(5)开漏输出_OUT_OD ——IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但         由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变。可以读     I O输入电平变化,实现C51的IO双向功能   
(6)推挽输出_OUT_PP ——IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的
(7)复用功能的推挽输出_AF_PP ——片内外设功能(I2C的SCL,SDA)
(8)复用功能的开漏输出_AF_OD——片内外设功能(TX1,MOSI,MISO.SCK.SS).
STM32设置实例:
(1)模拟I2C使用开漏输出_OUT_OD,接上拉电阻,能够正确输出0和1;读值时 先GPIO_SetBits(GPIOB, GPIO_Pin_0);拉高,然后可以读IO的值;使用GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0);
(2)如果是无上拉电阻,IO默认是高电平;需要读取IO的值,可以使用带上拉输入_IPU和浮空输入_IN_FLOATING和开漏输出_OUT_OD;
以上内容摘抄于openedv论坛上一位学长的帖子(先学者为学长嘛)
u     3种最大输出速度:
      -2MHZ
      -10MHz
      -50MHz
STM32有很多I/O口兼容3.3V5VLevel标有FT的就是兼容的)
有关寄存器的知识
       每个I/O口都由7个寄存器控制
232位的端口配置寄存器CRLCRH
CRL复位值为0X44444444;CRL寄存器控制着每组I/O端口的低8位的模式和输出速率;每个I/O端口的位占用CRL的4个位,高两位为CNF,低两位为MODE。CNF位(两位)在输入模式下【MODE[1:0]=00{(00表示模拟输入模式),(01表示浮空输入模式),(10表示上拉/下拉输入模式),(11表示保留在输出模式)}MOD位(两位):{(00表示输入模式),(01表示输出模式10MHZ),(10表示输出模式2MHZ),(11表示输出模式50MHZ)}
PxODR寄存器位和设置上拉输入(0/下拉输入有关(1;???
模式:NCF7[1:0]MODE7[1:0]………………………..NCF0[1:0]MODE0[1:0]
CRH寄存器控制着每组I/O端口的高8位的模式和输出速率。
232位的数据寄存器IDRODR
IDR是一个端口输入数据寄存器,只用了低16位,高16位都保留为0;该寄存器为只读寄存器。要想知道某个I/O口的电平状态,只要读取这个寄存器就可以了。
ODR是一个端口输出寄存器,只用了低16位,高16为都保留为0;该寄存器为可读/写寄存器。从该寄存器读出的数据可以用来判断当前I/O的输出状态。而向该寄存器写数据则可以控制某个I/O口的输出电平。
132位的置位/复位寄存器BSRR
BSRR寄存器是端口位设置/清除寄存器,可以用来设置GPIO端口的输出位。32个位只能写入并只能以字的形式操作。
写0对【高16位】来说【对相应的ODR位不产生影响】
对【低16位】来说【清除对应的ODR位为0,也就是让相应的I/O口的端口值为1】
写1对【低16位】来说【对相应的ODR位不产生影响】
对【高16位】来说【设置对应的ODR位为1,也就是让相应的I/O口的端口值为0】
低16位设置优先于高16位
116位的复位寄存器BRR
BRR寄存器是端口位清除寄存器,作用和BSRR的高16位类似。
132位的锁存寄存器LCKR
重要函数:
1个初始化函数:
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef*GPIO_InitStruct);
2个读取输入电平函数:
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_tGPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
2个读取输出电平函数:
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
4个设置输出电平函数:
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);    //常用
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);  //常用
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitActionBitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
1个初始化函数:
  voidGPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
  作用:初始化一个或者多个IO口(同一组)的工作方式和速度。该函数主要是操作GPIO_CRL(CRH)寄存器,在上拉或者下拉的时候有设置BSRR或者BRR寄存器。(GPIOx: GPIOA~GPIOG)
注意:外设(包括GPIO)在使用之前,几乎都要先使能对应的时钟。
初始化样例
GPIO_InitTypeDef  GPIO_InitStructure; //加粗部分为结构体
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);        //根据设定参数初始化GPIOB.5
结构体原型如下:
typedefstruct
{
    uint16_t GPIO_Pin;                           //指定要初始化的IO口         
    GPIOSpeed_TypeDef GPIO_Speed; //设置IO口输出速度
    GPIOMode_TypeDef GPIO_Mode;    //设置工作模式:8种中的一个
}GPIO_InitTypeDef;
使能IO口时钟:调用函数RCC_APB2PeriphColckCmd();
操作IO口,输出高低电平。GPIO_SetBits();//变高GPIO_ResetBits();//变低
格式如下GPIO_SetResetBits(GPIOX,GPIO_Pin_N);//PX_N变高(变低)
注意:在使用任何外设的函数或其它函数之前,要注意初始化
Program Size: Code=4980RO-data=336 RW-data=56ZI-data=1832(编译后生成的语句)  
Code表示程序占用Flash的大小
ROdataRead Onlydata表示已被程序定义的常量,如const类型(Flash
RWdataRead Writedata,表示已被初始化的全局变量(SRAM
ZIdataZero Initdata,表示未被初始化的全局变量(SRAM
有了这个就可以知道当前使用的FlashSRAM大小了。程序的大小不是生成.hex文件的大小而是编译后的CodeROdata之和。
I/O口有关的固件库函数有stm32f10x_rcc(处理内部时钟相关函数文件)、stm32f10x_gpio()
1019
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

84

帖子

0

精华

高级会员

Rank: 4

积分
529
金钱
529
注册时间
2015-7-21
在线时间
47 小时
发表于 2016-10-22 22:13:55 | 显示全部楼层
一名合格的工程师一定要做到,代码虐我千百遍依然待她如初恋!
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-22 22:21:58 来自手机 | 显示全部楼层
流水若冰 发表于 2016-10-22 22:13
不错学习的很仔细!

谢谢,回想以往学习的方法,真的是求快,不踏实,现在重新学习,但求一步一步。
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-22 22:23:44 来自手机 | 显示全部楼层
希望大家批评指教
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-23 10:19:12 | 显示全部楼层
第二天 按键输入实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求:按下Key_up键所有小灯状态翻转;按下Key0DS1状态翻转;按下Key1DS0状态翻转。
sys.h——这个头文件包含了原子的有关“位带操作,实现类似51类似的GPIO控制功能”的定义,其中包括:
   I/O口操作宏定义
              I/O口地址映射#define
              I/O口操作,只对单一的I/O口( 形如PXout(n)/ PXin(n)
              还有四个独立的汇编函数(速度更快)(备注:还不懂什么意思)
重要的事情:一定要使能相应的时钟!!!使能函数RCC_APB2PeriphClockCmd();
战舰板中Key0Key1Key2是接地的,所以使用下拉输入,Key_up与之相反。
在编写程序时,要注意硬件连接电路,然后判断使用输入/输出方式
原子例程中按键扫描函数使用了两种方式:支持连按和不支持连按。哦,对了,按键扫描要记得消抖。
switch语句
                     switch(x)
                     {
       Case 1;(执行语句)break
       Case 2;(执行语句)break
       Case 3;(执行语句)break………………
}
                                                                                                  
读取IO口输入电平调用库函数为:
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef*GPIOx, uint16_t GPIO_Pin);
使用位带操作读取IO口输入电平:Pxin(n) ——读取GPIOx.n口电平
C语言关键字 static
Static申明的局部变量,存储在静态存储区。
它在函数调用结束之后,不会被释放。它的值会一直保留下来。
所以可以说static申明的局部变量,具有记忆功能。
I/O口有关的固件库函数有stm32f10x_rcc(处理内部时钟相关函数文件)、stm32f10x_gpio()
1020
回复 支持 反对

使用道具 举报

5

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-16
在线时间
8 小时
发表于 2016-10-23 11:34:35 | 显示全部楼层
跟楼主进度差不多,共勉
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-23 14:00:08 | 显示全部楼层
小花酱 发表于 2016-10-23 11:34
跟楼主进度差不多,共勉

加油,稳稳的前进
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-23 15:01:57 | 显示全部楼层
第三天 串口实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求:在电脑中向串口发送字符串,并返回发送的字符;
串口操作相关库函数(省略入口参数):
voidUSART_Init(); //串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能
voidUSART_Cmd();//使能串口
voidUSART_ITConfig();//使能相关中断
voidUSART_SendData();//发送数据到串口,DR
uint16_tUSART_ReceiveData();//接受数据,从DR读取接受到的数据
FlagStatusUSART_GetFlagStatus();//获取状态标志位
voidUSART_ClearFlag();//清除状态标志位
ITStatusUSART_GetITStatus();//获取中断状态标志位
voidUSART_ClearITPendingBit();//清除中断状态标志位
串口配置的一般步骤:
①   串口时钟使能,GPIO和串口时钟使能:RCC_APB2PeriphClockCmd();
②   串口复位USART_DeInit(USARTx); 这一步不是必须的:
当外设出现异常情况的时候可以通过复位设置实现该外设的复位,然后重新配置这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。
③   GPIO端口模式设置:GPIO_Init(); //设置为相应的串口模式,发送为复用推挽输出,接收为浮空输入。
④   串口参数初始化:USART_Init();
⑤   开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)
      NVIC_Init();
      USART_ITConfig(USART_TypeDef*USARTx,uint16_t USART_IT_xxxx,ENABLE);
         第二个参数是标示使能串口的类型,格式如上xxxx位置,比如用RXEN取代,则表示在接收到数据时产生中断。
③④⑤放在一起,方便设定
⑥使能串口:USART_Cmd();
⑦编写中断处理函数:USARTx_IRQHandler();
发生了相应中断后,会跳到该函数执行。
通过USART_GetITStatus (usartx,USART_IT_RXEN);判断是否接收中断      //函数返回值!=RESET0,则接收中断,=SET1),则不接收中断。(判断中断是哪种中断,使用该函数,并不是只用来判断这一种。)
⑧串口数据收发:
void USART_SendData();//发送数据到串口,DR
uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据
函数配合数组USART_RX_BUF[]USART_RX_BU的大小有USART_REC_LEN定义,一个接收状态寄存器USART_RX_STA(它其实是一个全局变量,起到类似寄存器的作用)实现对串口数据的接收管理。USART_RX_STA寄存器(16位):最高位(15)为接收完成标志,第二位为接收到0x0D标志,剩下14位为收到的有效数据个数。
⑨串口传输状态获取:
FlagStatusUSART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
void USART_ClearITPendingBit(USART_TypeDef*USARTx, uint16_t USART_IT);//
串口状态有关:
通过寄存器USART_SR(32位)读取,高22位保留,这里需要注意第7位(6)TC和低6位(5)RXEN。
RXEN(读数据寄存器非空),置1时表示数据被接收到并可以读取出来,这时要做的是尽快读取USART_DR,从而将该位清0;也可以向该位写0,直接清除。
TC(发送完成):当该位被置位时,表示USART_DR内的数据已经被发送完成了,如果设置了这个位的中断,则会产生中断。两种清0方式:1)直接写0;2)读USART_SR,写USART_DR。
FlagStatusUSART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);//读取串口状态的函数,返回第二个参数的值,第二个参数为要查看的寄存器。
原子提供了usart文件,用于串口的初始化和中断接收,只是针对串口1,要使用其它串口需要对其进行修改。
串口有关的固件库函数有stm32f10x_usart
                                                                                                                       1021

回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-23 15:03:28 | 显示全部楼层
第四天 外部中断实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求:按Key0LED0的状态翻转;按Key1LED1的状态翻转;按Key2LED0LED1的状态一起翻转;按WK_UP,蜂鸣器的状态翻转
..\OBJ\EXIT.axf: Error: L6218E: Undefinedsymbol EXTIX_Init (referred from main.o).
Not enough information to list image symbols.在编写代码时遇到的错误,要注意调用函数的大小写!!!
STM32F103一共19个外部中断:线0-15—对应外部中断0-15的输入中断
                                                    线16—连接到PVD输出
                                                    线17—连接到RTC闹钟时间
                                                    线18—连接到USB唤醒事件
EXTI0_IRQHandler           
EXTI1_IRQHandler
EXTI2_IRQHandler           
EXTI3_IRQHandler           
EXTI4_IRQHandler      //线04各使用一个中断服务函数     
EXTI9_5_IRQHandler    //线59共同使用一个中断服务函数     
EXTI15_10_IRQHandler  //线1015共同使用一个中断服务函数     
使用I/O口外部中断的一般步骤
①   初始化I/O口作为输入
将想要使用的I/O口初始化作为中断
②   开启AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);开启APB2上的时钟就使用它
③   设置I/O口与中断线的映射关系
GPIO_EXTILineConfig(GPIO_PortSourceGPIOX,GPIO_PinSourcen);
④   初始化线上中断,设置触发条件等
EXTI_Init(&EXTI_InitStructure);//也是使用结构体
typedef struct
{
  uint32_t
EXTI_Line; //中断线的标号EXTI_Linex            
  EXTIMode_TypeDefEXTI_Mode; //中断模式:中断EXTI_Mode_Interrupt
                                                                                     事件EXTI_Mode_Event     
EXTITrigger_TypeDef EXTI_Trigger; //触发方式:
上升沿触发EXTI_Trigger_Rising
下降沿触发EXTI_Trigger_Falling
上升沿或下降沿触发EXTI_Trigger_Rising_Falling
FunctionalState EXTI_LineCmd;   //使能中断线ENABLE
}EXTI_InitTypeDef;
⑤   配置中断分组(NVIC),并使能中断
NVIC_Init(&NVIC_InitStructure);//结构体,使用结构体参数前记得加&
Typedef struct
{
  uint8_tNVIC_IRQChannel;//使能I/O口外部中断通道EXTIx_IRQn
  uint8_tNVIC_IRQChannelPreemptionPriority;//设置抢占优先级0x0n
  uint8_tNVIC_IRQChannelSubPriority;//设置子优先级0x0n
FunctionalState NVIC_IRQChannelCmd;//使能外部中断通道ENABLE
} NVIC_InitTypeDef;
①—⑥放在一个函数中作为中断初始化函数
⑥   编写中断服务函数
常用的中断服务函数格式
void EXTIX_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Linex)!=RESET)//判断某个线上的中断是否发生
{
        中断逻辑。。。。。。。
        EXTI_ClearITPendingBit(EXTI_Line2);//清除线上的中断标志位
}
}
EXTI_GetFlagStatus()直接用来判断标志位
EXIT_ClearFlag()清楚线上的中断标志位
注意:永远都不要忘记使用所有需要的初始化函数!!!
外部中断使用的有关固件库函数有stm32f10x_exti
                                                                                                                       1022
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-23 15:05:07 | 显示全部楼层
独立看门狗实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求:每两秒独立看门狗会复一次位,使用WK_UP按键在计数器为0之前来喂狗,使其不复位。
STM32的独立看门狗由内部专门的40KHZ低速时钟驱动,及时主时钟发生故障,他也仍然有效,这个时钟是一个内部RC时钟,所以并不是很准确的40KHZ。看门狗对时钟的要求不是那么精确,所以有所偏差是可以接受的。
看门狗的作用:就是在一定时间内(通过定时计数器实现)没有接收喂狗信号(表示MCU已经挂了),便实现处理器的自动复位重启。
有关的键值寄存器IWDG_KR32位):高16位保留,始终读为0;低16位,只写,读出值为0x0000
软件必须以一定的时间间隔写入0xAAAA,否则当计数器为0时,看门狗会产生复位,这个操作。写入0xCCCC,开始启用独立看门狗,此时计数器开始递减计数,并且可以访问IWDG_PRIWDG_RLR(具有写保护功能,向IWDG_KR写入0xAAAA会启动写保护功能)
独立看门狗函数配置:
voidwdog_Init(void)
{
       IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//取消寄存器写保护(向IWDG_KR写入0x5555
       IWDG_SetPrescaler(prer);//设置IWDG预分频值(0-7
       IWDG_SetReload(rlr);//设置IWDG重装载值(<4096
Tout=((4*2^prer*rlr/40;//Tout表示看门狗减计数到0的时间(ms
       IWDG_ReloadCounter();重新装载计数值喂狗(向IWDG_KR写入0xAAAA
       IWDG_Enable();       //启动独立看门狗
}
注意:独立看门狗一旦启用,就不能再被关闭!想要关闭只能重启,并且重启之后,不能打开看门狗,否则问题依旧。如果不用IWDG的话,就不要打开它,免得麻烦。
独立看门狗使用有关固件库函数有stm32f10x_iwdg
                                                                                                                       1022
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-23 15:05:36 | 显示全部楼层
第五天窗口看门狗实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求:通过LED0来指示STM32是否被复位,如果被复位了就会点亮LED0.5sLED1来指示是否喂狗,喂狗一次LED1的状态翻转一次。
配置窗口看门狗过程:
①    使能WWDG时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
//WWDG使用的是PCLK1的时钟
②    设置窗口值和分频数
有关寄存器WWDG_CR和WWDG_CFR
  窗口看门狗的超时公式:
Twwdg=(4096*(2^WDGTB)*(WWDG_CR[5:0]+1))/Fpclk1
  Twwdg为WWDG的超时时间(ms),Fpclk1为APB1的时钟频率(KHZ)
  WDGTB位WWDG的预分频系数
WWDG_CR(控制寄存器32位)只有低8位(7-0)有效,低7位(6-0)用来储存看门狗的计数器值为每个窗口看门狗计数周期(4096*2^WDGTB),该计数器的值从0x40变为0x3f的时候,将会产生看门狗复位;第8位(7)WDGA是看门狗的激活位,由软件置1,启动看门狗,该位一旦设置,只能在硬件复位后才能清零。
WWDG_CFR(配置寄存器32位)只有低10位有效,第10位(9)EW1若置1,则当计数器达到0x40时,则产生中断,进入中断后,必须在不大与一个窗口看门狗计数周期的时间内重新写WWDG_CR,否则看门狗将产生复位;此中断只能由硬件在复位后清除;第9、8位(8、7)WDGTB[1:0]预分频系数;低7位(6-0)7位窗口值,包含了用来与递减计数器进行比较所用的窗口值(0x40)。
WWDG_SetPrescaler(WWDG_Prescaler_8);//设置看门狗的分频系数
WWDG_SetWindowValue(0x7F);//设置看门狗的上窗口值
③    开启WWDG并分组
WWDG_EnableIT();//开启窗口看门狗中断
NVIC_Init();//中断优先级配置
④    设置计数器初始值,同时使能窗口看门狗
WWDG_Enable(x);//<=0x7f&>=0x40。
⑤    编写中断服务函数
WWDG_SR(状态寄存器32位)只有0位有效。当计数器达到0x40时,此位由硬件置1;通过软件写0来清楚,写1无效。即使中断未被使能,在计数器的值达到0x40时,此位也会被置1.
喂狗要快,然后将状态寄存器中的EWIF清空。
WWDG_SetCounter(0X60);//喂狗,重新装载初始值
       WWDG_ClearFlag();//将状态寄存器中的EWIF清空
窗口看门狗使用的固件库函数有stm32f10x_wwdg
                                                                                                                       1023

回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-23 21:38:55 | 显示全部楼层
定时器中断实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求:利用定时器让LED0每隔1S状态翻转一次,用LED1表示程序正在运行。
   STM32F1有两个高级定时器TIME1TIME8。四个通用定时器TIME2~TIME5、两个基本定时器TIME6TIME7
      STM32F1的通用定时器是由一个可编程预分频器PSC驱动的16位自动装载计数器CNT构成,可用于测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)等。每个通用定时器都是完全独立的,没有互相共享任何公用资源。
  STM32F1通用定时器的功能
(1)     16位向上、向下和向上/向下自动装载计数器(TIMx_CNT)
(2)     16位可编程预分频器(TIMx_PSC),计数器时钟频率的分频系数为1~65535之间的任意值。
(3)     4个独立通道(TIMx_CH1~4,这些通道可以作为:输入捕获、输出比较、PWM生成(边缘或中间对齐模式)或单脉冲模式输出。
(4)     可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用一个定时器控制另外一个定时器)的同步电路。
(5)     如一下事件发生时产生中断/DMA
1.       更新:计数器向上/向下溢出,计数器初始化(通过软件或者内部/外部触发);
2.       触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
3.       输入捕获
4.       输出比较
5.       支持针对定位的增量(正交)编码器和霍尔传感器电路
6.       触发输入作为外部时钟或者按周期的电流管理。
还有更多有关的知识在《STM32参考手册》
定时器的使用步骤(使用TIM2):
①   使能TIMx时钟
TIM2挂在APB1下,所以使用APB1总线下的使能函数
②   初始化定时器参数,设置自动装载初值、分频系数、计数方式等
控制寄存器1TIMx_CR116位),最低位0CEN为计数器使能位,置1让定时器开始计数;1UDIS为禁止更新;2URS为更新请求源;3OPM为单脉冲模式;4DIR为方向,置0,向上计数,置1,向下计数;6:5CMS为选择对齐模式;7ARPE为自动重装载预装载允许位;9:8CKD为时钟分频因子。其它位保留。

   预分频计数器TIMx_PSC(16)16位来表示预分频器的值,计数器的时钟频率CK_CNT=Fck_psc/(PSC[15:0]+1),PSC包含了当更新事件产生时装入当前预分频器的值。
这里定时器的时钟来源有4
1.      内部时钟CK_INT(来源于APB1倍频)
2.      外部时钟模式1:外部输入脚(TIx
3.      外部时钟模式2:外部触发模式(ETR
4.      内部触发模式(ITRx:使用A定时器作为B定时器的预分频器(AB提供时钟)
这些时钟具体选择哪个可以通过TIMx_SMCR寄存器的相关位进行设置

定时器的计数器寄存器TIMx_CNT,储存了当前定时器的计数值。
自动重装载寄存器TIMx_ARR16位)物理上对应两个寄存器,一个可以直接操作,另外一个叫做“影子寄存器”真正起作用的是影子寄存器,根据TIMx_CR1寄存器中APRE位的设置:APRE=0时,预装载寄存器的内容可以随时传送到影子寄存器中;APRE=1时,在每一次更新事件(UEV)时,才把预装载在寄存器的内容传送到影子寄存器中。
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//定时器初始化
typedef struct
{
uint16_t TIM_Prescaler;//分频系数psc
uint16_t TIM_CounterMode;
//计数方式,比较常用的是TIM_CounterMode_Up和TIM_CounterMode_Down
uint16_t TIM_Period;//自动重载计数周期值arr
uint16_t TIM_ClockDivision;//时钟分频因子 TIM_CKD_DIV1
                                                                           TIM_CKD_DIV2
                                                                           TIM_CKD_DIV3
uint8_t TIM_RepetitionCounter;//高级定时器用。
} TIM_TimeBaseInitTypeDef;
Tout=((arr+1)*(psc+1))/Tclk   (Tclk为TIM2的输入时钟频率,MHZ) (Tout为TIM2溢出时间,us)
③   设置TIM2_DIER允许更新中断
DMA/中断使能寄存器TIMx_DIER16位),这里仅使用了第0UIE(更新中断允许位),置1来允许由于更新事件所产生的中断。(剩余位有的是其它中断的允许位和其它DMA相关允许位)。
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//第二个参数为定时器中断类型,包括更新中断TIM_IT_Update、触发中断TIM_IT_Trigger以及输入捕获中断等等
④   TIM2中断优先级设置
NVIC_Init(&NVIC_InitStructure);//没什么说明的必要了
⑤   使能TIM2
TIM_Cmd(TIM2,ENABLE);
⑥   编写中断服务函数
状态寄存器TIMx_SR16位)标记当前与定时器相关的各种事件/中断是否发生。
void TIM2_IRQHandler(void)//这里是规定好的(2可以更改,剩下一点也不能错
{
      if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)//读取中断状态寄存器的值从而判断中断类型。第二个参数的意思在上面。
     {
          TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位
          中断逻辑。。。。。。。。。。
     }     
}
定时器有关的固件库函数有stm32f10x_tim

今天因为粗心改变了中断函数的函数名,而在寻找错误耽误了很多时间,也因此再次提醒了自己要仔细、认真!
                                                                                                                                             10月23日

回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2016-10-23 22:34:42 | 显示全部楼层
加油,骚年
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-23 22:50:55 来自手机 | 显示全部楼层
龙之谷 发表于 2016-10-23 22:34
加油,骚年

谢谢,,, 当初也是看了你的帖子,于是想到要笔记 请多多指教。感谢!!!
回复 支持 反对

使用道具 举报

26

主题

280

帖子

1

精华

高级会员

Rank: 4

积分
908
金钱
908
注册时间
2013-8-2
在线时间
279 小时
发表于 2016-10-24 09:49:55 | 显示全部楼层
写在论坛排版有些乱,建议发到csdn上。
我也写资料,发一篇博文格式可以给你供参考。
《STM32之霍尔传感器模块》:http://blog.csdn.net/feilusia/article/details/52873885
博客:http://blog.csdn.net/feilusia
CC2541群(127442605);CC2640群(557278427);
Android群(541462902);STM8/STM32群(164311667);
Linux群(512598061);职场交流群(450154342);
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-24 10:11:53 来自手机 | 显示全部楼层
哦哦 谢谢你的建议
回复 支持 反对

使用道具 举报

44

主题

298

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
209
金钱
209
注册时间
2016-9-9
在线时间
84 小时
发表于 2016-10-24 10:44:55 | 显示全部楼层
如果楼主每次都这么认真,我将一直关注
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-24 11:41:02 来自手机 | 显示全部楼层
dreamARM 发表于 2016-10-24 10:44
如果楼主每次都这么认真,我将一直关注

谢谢! 会加油的!
回复 支持 反对

使用道具 举报

5

主题

101

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
259
金钱
259
注册时间
2013-4-4
在线时间
46 小时
发表于 2016-10-24 13:09:10 | 显示全部楼层
支持!加油加油!
回复 支持 反对

使用道具 举报

0

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
103
金钱
103
注册时间
2016-10-12
在线时间
28 小时
发表于 2016-10-24 13:14:54 | 显示全部楼层
加油,持续关注中,楼主坚持啊
回复 支持 反对

使用道具 举报

28

主题

176

帖子

0

精华

高级会员

Rank: 4

积分
738
金钱
738
注册时间
2014-7-1
在线时间
180 小时
发表于 2016-10-24 13:27:00 | 显示全部楼层
支持你!!
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-24 15:24:57 来自手机 | 显示全部楼层
xiaomiking 发表于 2016-10-24 13:09
支持!加油加油!

谢谢 一起加油
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-24 15:25:39 来自手机 | 显示全部楼层
zmxhl 发表于 2016-10-24 13:14
加油,持续关注中,楼主坚持啊

嗯嗯 加油!!!
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-24 15:26:04 来自手机 | 显示全部楼层
qingyu111 发表于 2016-10-24 13:27
支持你!!

谢谢支持
回复 支持 反对

使用道具 举报

5

主题

101

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
259
金钱
259
注册时间
2013-4-4
在线时间
46 小时
发表于 2016-10-24 18:58:54 | 显示全部楼层

你比我学习的要深入
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-24 21:14:27 | 显示全部楼层
xiaomiking 发表于 2016-10-24 18:58
你比我学习的要深入

可以看看我记得笔记,这里的东西大部分都是原子哥书上的东西,原子哥写的书真的是很棒,配合上《STM32F1开发指南-寄存器版本_V3.1 》和《STM32中文参考手册_V10》,完美!!!
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-24 21:31:14 | 显示全部楼层
第六天PWM输出实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求:使用定时器3的通道2产生PWM控制led0的亮灭,实现由暗到亮、由亮到暗的过程。
脉冲宽度调制(PWM),简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术;就是对脉冲宽度的控制。
高级定时器可以产生7PWM输出,通用定时器4路。
配置函数的过程
①    开启TIM3时钟以及复用功能时钟,配置PB5为复用输出
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
GPIO_Init();//用过多次了,注意别出错,要仔细
②    设置TIM3_CH2重映到PB5
STM32的重映射控制是由复用重映射和调试I/O配置寄存器AFIO_MAPR控制的,现在需要使用的是第12、11位[11:10](其他各位都是相关的配置,看一下就知道,太多了,就不摘抄在这里了),
上图是TIM3_REMP重映射控制表,我们想要把TIM3_CH2映射到PB5上,所以设置TIM3_REMP[1:0]=10,即部分重映射。注意,此时TIM3_CH1也被重映射到PB4上了。
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);//看寄存器部分
③    初始化TIM3,设置TIM3ARRPSC
设置这两个寄存器的值来控制输出PWM的周期,当PWM周期太慢(低于50KHZ)的时候,就会明显感觉到闪烁了。PWM周期不能太小。//
PWM频率=7200/psc//(arr+1)
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);//结构体参数参考昨天的
④    设置TIM3_CH2PWM模式(默认冻结),使能TIM3CH2输出
捕获/比较模式寄存器(16位)TIMx_CCMR1/2该寄存器有两个,1控制CH1和CH2,2控制CH3和CH4;该寄存器的某些位在不同模式下功能不一样,这里要说明的是OC2xM,此位由3位组成,可配置成七种模式(下面有提到)。
  捕获/比较使能寄存器(16位)TIMx_CCER,CCxP位设置OCx的极性,CCxE位控制OCx(输入/捕获x输出)的使能。
TIM_OC2Init(TIM3,&TIM_OCInitStructure);//设置PWM_CH2的PWM模式,这里2表示通道数,3表示定时器数,使用哪个就用哪个。
typedef struct
{
  uint16_t TIM_OCMode;//设置模式
1.      TIM_OCMode_Inactive输出比较非主动模式(匹配时设置输出引脚为无效电平,当计数器值与比较/捕获寄存器值相同时强制输出为低电平)。
2.      TIM_OCMode_Active输出比较主动模式(匹配时设置输出引脚为有效电平,当计数值与比较/捕获寄存器值相同时,强制输出为高电平)
3.       TIM_OCMode_PWM1是在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为 无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。
4.      TIM_OCMode_PWM2和模式1相反,也类似
5.      TIM_OCMode_Timing输出比较时间模式(输出引脚冻结无效){是在比较成功后不在对应输出管脚上产生输出。}
6.      TIM_OCMode_Toggle是在比较成功后翻转对应输出管脚上的电平。
uint16_tTIM_OutputState;//比较输出使能/不使能
uint16_t TIM_OutputNState;//互补输出使能,开启/关闭OC*n输出到对应引脚
uint16_tTIM_Pulse;//比较/PWM通道的值
uint16_tTIM_OCPolarity; //设置极性高低TIM_OCPolarity_Low/High
uint16_tTIM_OCNPolarity;//也是设置极性的(具体没有找到,先不急)
uint16_t TIM_OCIdleState;//当MOE=0时如果实现了OC*n则死区后OC*n=1/0。(具体也不太懂,再查查吧,先写在这里)
uint16_tTIM_OCNIdleState;和上面的类似(也不懂)
}TIM_OCInitTypeDef;
这里只用到了其中三个,剩下的是高级定时器用到的,明天的会具体讲述
⑤    使能TIM3
TIM_Cmd(TIM3,ENABLE);
⑥    修改TIM_CRR2来控制占空比
捕获/比较寄存器TIMx_CRR1~4,4个寄存器对应4个通道。该寄存器装入了当前捕获/比较寄存器的值(预装载值),修改这个寄存器的值就可以控制相应通道PWM的输出脉宽。
经过以上设置后,PWM其实已经开始输出了,只是占空比和频率都是固定的。修改TIM_CRR2占空比的函数是:
        TIM_SetCompare2(TIM3,pwmnum);//第二个参数为PWM的比较值,让pwmnum的值从小到大再从大到小就能达到我们想要达到的目的了,这里设置最大为300。
   这里用来告诫自己:一定要仔细!一定要仔细!一定要仔细!不要对每一个字母大意,一时大意,事后要用很多很多的时间和精力来寻找自己所犯下的错,这是很不值得的。今天的课很多,几乎占用了大部分时间,我也因此想过今天先休息一下,少学一点,但是想到自己定下了目标,便不能放弃,于是鼓励自己坚持,我可以的。也许我以后的课会更多,可是我不能因此而放弃我自己为自己定下的学习计划。可能是我操之过急,也是我粗心大意。无论怎样,我相信我坚持下去,多学多练,一定会越来越熟练,加油!!!
PWM有关的固件库函数有stm32f10x_tim

                                                                                                       10月24日
回复 支持 反对

使用道具 举报

5

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2016-5-29
在线时间
19 小时
发表于 2016-10-24 22:46:48 | 显示全部楼层
楼主和我一样啊,我也是把前面的基础都看完了,但是好多没理解,也没做实验,就洗了糊涂的看一个视频!,结果发现往后越看越看不懂了,回想起以前的该忘的都忘了,也是下定决心又来了一遍,力求每个视频细细的研究,不彻底搞懂绝不看下面的视频,目前学习3个月了,第二遍已经看到了图片显示了!现在正在JEPG图片解码这里虐的死去活来,什么霍夫曼啊,余弦,一脸懵逼在考虑是否有必要学一下高等数学!感觉不把每个应用函数研究透,就不能灵活的运用这个函数,不能胸有成竹的写程序。一想到高等数学,哎,我这个初中毕业生当初怎么就不好好学习呢、。。。。。。
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-25 07:00:18 来自手机 | 显示全部楼层
15904520807 发表于 2016-10-24 22:46
楼主和我一样啊,我也是把前面的基础都看完了,但是好多没理解,也没做实验,就洗了糊涂的看一个视频!,结 ...

加油!! 都已经图片显示了, 很六了, 都已经学到这里 ,再多学一点也好,共勉!
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2016-3-3
在线时间
8 小时
发表于 2016-10-25 16:40:14 | 显示全部楼层
楼主好样的加油!持续关注!
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
25
金钱
25
注册时间
2016-3-9
在线时间
5 小时
发表于 2016-10-25 16:47:15 | 显示全部楼层
我也才学到PWM
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-25 16:58:51 来自手机 | 显示全部楼层
zengyaolong 发表于 2016-10-25 16:40
楼主好样的加油!持续关注!

谢谢!会加油的
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-25 17:00:57 来自手机 | 显示全部楼层
我叫刘子清 发表于 2016-10-25 16:47
我也才学到PWM

不急的 一点一点来。。。一着急就出错,今天学习输入捕获,着急吃饭,就产生错误。吃完饭回去继续撸!!!
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-25 21:23:39 | 显示全部楼层
第六天输入捕获实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求:利用通用定时器TIM5来捕获WK_UP按键按下的时间(PA0上的高电平脉宽),通过串口打印高电平脉宽时间。
       需要的寄存器有:TIMx_ARRTIMx_PSCTIMx_CCMRTIMx_CCERTIMx_DIERTIMx_CR1TIMx_CCR1
      
输入捕获函数配置步骤:
①   开启TIM5时钟和GPIOA时钟,配置PA0为下拉
TIMx_ARR设置自动装载值、TIMx_PSC设置时钟分频
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);  
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//没什么好解释的,一目了然   
        
②   初始化TIM5,设置TIM5ARRPSC
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);//结构体参数参考昨天的

③   设置TIM5的输入比较参数,开启输入捕获
捕获/比较模式寄存器TIMx_CCMR1(16位),这里因为用的是通道1,所以用到低8位。(通道2用高八位,通道3、4用TIMx_CCMR2寄存器)
位[7:4]ICF1输入捕获滤波器,定义了TI1输入采样频率及数字滤波器长度,数字滤波器由一个事件计数器组成,它记录到n个事件后会产生一个输出的跳变。设置为0,无 滤波器,以f(DTS)采样,f(DTS)根据TIMx_CR1的CKD[1:0]设置来确定的;剩余使用查看《STM中文参考手册》,假设设置为0011,当捕获到上升沿/下降沿的时候,在以定时器的输入频率连续采样8次,如果都是高电平/低电平,那么说明确实是一个有效的触发,就会触发输入捕获中断,这样可以滤除那些电平脉宽低于8个采样周期的脉冲信号,达到滤波的效果。
位[3:2]IC1PSC输入/捕获预分频器,定义了CC1输入的预分频系数,设为0,无预分频器,捕获输入口上检测到每一个边沿都触发一次捕获,01:2次事件,10: 4次事件,11: 8次事件。
位[1:0]CC1S捕获/比较选择,定义通道的方向及输入脚的选择,设为00:CC1通道为输出,01:CC1通道为输入,映射在IT1上,10:输入,映射到IT2上,11:映射到RTC(仅工作在内部触发器输入被选中时)。
TIM_ICInit(TIM5, &TIM5_ICInitStructure);//初始化TIM5的输入比较参数
typedef struct
{
  uint16_tTIM_Channel;//设置通道
  uint16_tTIM_ICPolarity;//有效捕获极性
  uint16_tTIM_ICSelection;//设置映射关系
  uint16_tTIM_ICPrescaler;//设置捕获分频系数,这里TIM_ICPSC_DIV1(不分频),还有2、4、8分频可选  
  uint16_tTIM_ICFilter;//设置滤波器长度,这里不分频,设置为0   
} TIM_ICInitTypeDef;
④   使能捕获和更新中断
捕获/比较使能寄存器TIMx_CCER,这里用到了最低两位CC1E和CC1P,
CC1P输入/捕获1输出极性;CC1通道配置为输出时,0:OC1高电平有效 1:低电平有效;CC1通道为输入时,0:不反相,捕获发生在IC1的上升沿,当用作外部触发器时,不反相;1:与设置0时相反。
CC1E输入/捕获1输出使能;CC1通道为输出时,0:关闭-OC1禁止输出,1:开启OC1信号输出到对应引脚上;CC1通道配置为输入时,决定了计数器的值是否能捕获输入TIM_CCR1寄存器,0:捕获禁止,1:捕获使能。
(昨天的没有这个,今天补上。)
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//前面有介绍

⑤   设置中断分组,编写中断服务函数
捕获/比较寄存器1 TIMx_CCR1,该寄存器用来储存捕获发生时,可以从该寄存器中读出通道1发生时刻的TIMx_INT值,通过两次捕获的差值就可以计算出电平脉冲的宽度。
NVIC_Init(&NVIC_InitStructure);//设置中断分组,前面有介绍
void TIM5_IRQHandler(void)//中断服务函数,名字不能改变
中断开始时要进行中断类型判断,中断结束时要清楚标志位
if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//是否发生捕获事件
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)//是否为更新中断
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update);//清楚标志位

中断服务函数设计思路:
这里定义了两个全局变量TIM5CH1_CAPTURE_STA(当成寄存器来使用)和TIM5CH1_CAPTURE_VAL,前者用来记录捕获状态,最高位为捕获完成标志位,第7位为捕获到高电平标志位,低6位为捕获电平后定时器溢出的次数;后者用来记录捕获到下降沿时TIM_INT的值。
首先,设置TIM_CH1捕获上升沿(在初始化的时候就设定好了),然后等待上升沿到来。当捕获到上升沿时,如果STA的第7位为0,则表示还没有捕获到新的上升沿,就先把STA、VAL和TIM5_INT清零,然后,设置STA第7位为1,标记捕获到高电平。最后,设置为捕获下降沿,等待下降沿到来。如果等待下降沿期间定时器发生了溢出,就在STA里面对溢出次数进行计数,当最大溢出次数来到的时候,就强制标记捕获完成。当下降沿到来的时候,先设置STA的第八位为1,标记成功捕获了一次高电平,然后读取此时的定时器值到VAL里面,最后设置为上升沿捕获,回到初始状态。
这样就完成一次高电平的捕获了,只要STA最高位一直为1,就不会进行第二次捕获。Main函数处理完捕获数据后,将STA置0,就可以开启第二次捕获了。
TIM_OCnPolarityConfig(TIMx,TIM_ICPolarity)修改TIMx_CHn的极性
TIMx,TIM_ICPolarity_Falling //下降沿 TIM_ICPolarity_Rising//上升沿 TIM_ICPolarity_BothEdge//上升沿/下降沿
TIM_SetCounter(TIM5,0);//设置计数器寄存器值
⑥   使能定时器
控制寄存器TIMx_CR1,只用它的最低位来使能定时器
TIM_Cmd(TIM5,ENABLE);
把原子哥的设计思路完全照抄下来到这里的,是因为想让自己弄懂,库函数的配置难度不是很高,只要认真、够仔细,再查一查《STM32中文参考手册》,还是没什么大问题的。我认为程序的设计思路是很重要的,现在我能做到的只是能看懂他人的设计,我应该做到有自己的设计思想,考虑问题要完善。加油!!!每天都在进步!!!
                                                                                                             10月25日

回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-25 21:39:01 | 显示全部楼层
每天学习实验大概分成三步:
                                      1、先看书,了解一下这个实验是要干嘛的,有什么用处;熟悉一下相关寄存器和库函数的配置过程。                                      2、写代码,包括HARDWARE里的c文件和h文件还有主函数,修改、完善,最后思考期间犯下的错误,总结配置过程。
                                      3、写笔记,记下实验内容和相关简介,按照库函数的配置步骤来记笔记,将相关的寄存器说明记在相应的步骤下,思考有什么需要改进的地方,总结一次的学习。
  每一天都在进步,很好,坚持下去,才更好。
  明天学习TFTLCD显示实验,感觉有所难度,所以打算使用3天的时间来学习,也许会加快进度,因为不了解,所以先定下这个时间,加油!今天过得也很充实,这很好。坚持!!!
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
25
金钱
25
注册时间
2016-3-9
在线时间
5 小时
发表于 2016-10-26 18:27:11 | 显示全部楼层
能加好友嘛,一起学习,我也是输入捕获这里 QQ:57DA 3A4B
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-26 21:32:06 | 显示全部楼层
我叫刘子清 发表于 2016-10-26 18:27
能加好友嘛,一起学习,我也是输入捕获这里 QQ:57DA 3A4B

额 这是啥qq,有点看不懂呀
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-26 21:35:04 | 显示全部楼层
第七天TFTLCD显示实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求:在LCD屏幕中央显示出自己的名字
第一天,看书 看代码理解LCD显示的原理,配置LCD
      
TFTLCD即薄膜晶体管液晶显示器,叫做真彩液晶显示器。采用16位并行方式与外部连接。
引脚介绍:
                                          CS:TFTLCD片选信号。
                                          WR:TFTLCD写入数据
                                          RD:从TFTLCD读取数据
                                          D[15:0]16位双向数据线
                                          RET:硬复位
                                          RS:命令/数据标志(0,读/写命令;1,数据)
   还有一个背光线来控制背光
驱动LCD的芯片有多种,不同的芯片驱动控制类似。以ILI9341为例。
ILI9341液晶控制器自带显存,其显存大小为172800320*240*18/8),即18万模式(26万色)下的显存量。在16位模式下,RGB565格式储存颜色数据,在MCU16位数据中,最低5位代表蓝色,中间6位代表绿色,最高5位代表红色,数值越大代表颜色越深。ILI9341所有的指令 都是8位的(高8位无效),且参数除了读/GRAM的时候是16位,其它操作参数都是8位的,这个和其它一些驱动器不一样。
ILI9341的重要指令有:0XD3,0X36,0X2A,0X2B,0X2C,0X2E
0XD3,这是读ID指令,用于读取LCD控制器的ID0X4D指令后面跟4个参数,最后两个参数代表ID,通过该指令即可判断出所用LCD驱动器是什么型号,这样,代码就可以根据控制器的型号去执行对应的初始化,从而兼容不同驱动的IC屏,使得一个代码支持多款LCD
0X36,这是储存访问控制指令,可以控制ILI9341储存器的读/写方向,就是在连续写GRAM的时候,可以控制GRAM指针的增长方向,从而控制显示方式(读GRAM也一样),0X36指令后面紧跟一个参数,这里[7:5]MYMXMV三个位,通过这三个位的设置,可以控制整个ILI9341的全部扫描方向。  000:从左到右,从上到下;100:从左到右,从下到上;等等,(采用000方式)
0X2A,这是列地址设置指令,在默认扫描方式下,该指令用于设置x坐标。该指令带有4个参数,实际上是两个坐标值:SC(起始>=0)和EC<=239),即地址的起始值和结束值。
0X2B,这是页地址设置指令,含两个坐标值SPEP
0X2C,这是写GRAM指令,发送该指令后,就可以往LCDGRAM里面写入颜色数据了,该数据支持连续写。数据有效位宽为16位,可以连续写入LCDGRAM值,而GRAM的地址将根据MY/MX/MV设置的扫描模式进行自增。例如,设置为默认方式,设置好起始坐标后,每写入一个颜色值,GRAM地址将会自动自增1SC++)。如果达到EC,则返回到SC,同时SP++,一直到ECEP结束。
0X2E,这是读GRAM指令,用于读取ILI9341的显存,ILI9341收到该指令后,第一次输出的是无效指令,从第二次开始读取到的才是有效的GRAM数据(SCSP开始),输出规律为:每个颜色分量占8位,一次输出2个颜色分量。比如第一次输出的是R1G1,随后的输出规律为B1R2,G2B2R3G3B3R4G4B4R5G5…以此类推。这里也用到了“自增”。
画点流程:设置坐标&#9758;GRAM指令&#9758;写入颜色数据
读点流程:设置坐标&#9758;GRAM指令&#9758;读取颜色数据。
有关的函数在程序中注释的很完美了,感觉不应该抄录在这里,需要使用的时候再去翻找就可以了。这些函数配合相关指令的介绍来看,很容易就了解了LCD的ILI9341相关设置。
今天,将LCD实验学习了一遍,学习到了很多,但是思路很混乱,所以就先记了这些。明天,将FSMC有关的知识和相关函数的知识再记录在笔记中。
感觉自己记笔记,就是把书上的内容COPY到了电脑上,有的时候会按照适合自己顺序重新排列,有的就是完全照抄下来;就像更精细的一个字一个字的学习原子哥的例程,学习原子哥的书,嘿嘿。在原子哥的书里,摘抄了一些感觉自己应该知道的东西,又抄了一遍在笔记上,发到了这里,希望原子哥不要介意哈。
                                                                                                                   1026

回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-26 21:41:00 | 显示全部楼层
感觉排版好糟糕啊,怎么破!求指教
回复 支持 反对

使用道具 举报

5

主题

101

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
259
金钱
259
注册时间
2013-4-4
在线时间
46 小时
发表于 2016-10-26 22:29:41 | 显示全部楼层
初心永恒 发表于 2016-10-26 21:41
感觉排版好糟糕啊,怎么破!求指教

给力给力,坚持坚持!
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2016-10-26 23:16:14 | 显示全部楼层
初心永恒 发表于 2016-10-26 21:41
感觉排版好糟糕啊,怎么破!求指教

已经有很大进步了
排版时内容分层次,逐层增大/减小字体,同一层字体相同,层间还可以使用空行分隔
还可以改变字体颜色,不要使用过多显得过乱即可
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-27 06:27:54 来自手机 | 显示全部楼层
xiaomiking 发表于 2016-10-26 22:29
给力给力,坚持坚持!

嗯嗯,谢谢
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-27 06:29:34 来自手机 | 显示全部楼层
龙之谷 发表于 2016-10-26 23:16
已经有很大进步了
排版时内容分层次,逐层增大/减小字体,同一层字体相同,层间还可以使用空行分隔
还 ...

嗯嗯 我试试增大字体。 不知道为什么本来调整好有的字显示颜色,结果发出来就都是黑色的了。
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-27 21:11:44 | 显示全部楼层
第八天TFTLCD显示实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
FSMC简介:
       FMSC即灵活的静态储存控制器,能够与同步或者异步储存器和16PC存储卡连接,STM32FSMC接口支持包括SRAMNANDFlashNOR FlashPSRAM等储存器。STM32FSMC将外部设备分为三类:NOR/PSRAM设备、NAND设备、PC卡设备。它们公用地址数据总线等信号,具有不同的CS以区分不同的设备。这里,LCD用的是FSMC_NE4作片选,其实就是将LCD当成SRAM来控制。
       外部SRAM的控制,一般有地址线、数据线、写信号、读信号、片选信号;如果SRAM支持字节控制,那么还有UB/LB信号。LCD的信号包括RSD0~D15WRRDCSRSTBL等,操作时用到的只有RSD0~D15WRRDCS。其操作时序和SRAM的控制完全类似,唯一不同的是,LCDRS信号,但是没有地址信号。
关于RS信号在明天的程序部分会有,这里越过。
STM32FSMC支持8/16/32位的数据宽度,这里用到的LCD16位宽度的,在设置时选择16位宽就可以了。FSMC的外部设备地址映像,STM32FSMC将外部的存储器划分为固定的大小为256MB4个存储块(Bank),这里用的BANK1,块相关的配置在参考手册的324页。
STM32FSMCBank1分为4个区,每个区管理64MB空间,每个区都由独立的寄存器对所连接的存储器进行配置。Bank1256MB空间有28根地址线      (HADDR[27:0])寻址。
HADDR是内部AHB地址总线,其中,HADDR[25:0]来自外部存储器地址FSMC_A[25:0],HADDR[26:27]对四个区进行寻址(我没有列出来,查找手册),当Bank1接的是16位宽度存储器时,HADDR[25:1]对应FSMC_A[240];Bank1接的是8位宽度存储器时,HADDR[25:0]对应FSMC_A[250]
不论外部接8/16位宽设备,FSMC_A[0]永远接在外部设备地址A[0]HADDR[26:27]的设置是不需要干预的,要做的就是配置对应第几区的寄存器组来适应外部设备就可以了。
NNOR Flash控制器主要通过FSMC_BCRxFSMC_BTRx、和FSMC_BWTRx寄存器进行设置(x对应4个区)。这三个寄存器可以设置FSMC访问外部存储器的时序参数,拓宽了可选用的外部存储器的速度范围。FSMCNORFlash控制器支持同步和异步突发两种访问方式。选用同步突发访问模式时,FSMCHCLK(系统时钟)分频后,发送给外部储存器作为同步时钟信号FSMC_CLK,此时需要设置的时间参数有两个:1.HCLKFSMC_CLK的分频系数(CLKDIV),可以分为2~16频;2.同步突发访问中获得第一个数据所需要的等待延迟(DATLAT)。
对于异步突发访问方式,FSMC主要设置3个时间参数:地址建立时间(ADDSET)、数据建立时间(DATAST)和地址保存时间(ADDHLD)。FSMC综合了SRAM/ROMPSRAMNORFlash产品的信号特点,定义了4中不同的异步时序模型。选用不同的时序模型时,需要设置不同的时序参数(这里有个表格,参考手册)。实际扩展时,根据选用存储器的特征确定时序模型,从而确定各时间参数与存储器读/写周期参数指标之间的计算关系;利用该计算关系和存储芯片数据手册中给定的参数指标,可计算出FSMC所需要的各时间参数,从而对时间参数寄存器进行合理的配置。
这里使用异步模式AModeA)凡是控制LCD模式A的读操作时序如图所示
       LCD读的时候一般比较慢,写的时候一般比较快,模式A支持独立的读/写时序控制,所以主要初始化的时候配置好,之后就不用配置了,既可以满足速度要求,又不需要频繁更改设置。
      
从上图可以看出,读操作还存在额外的2HCLK周期,用于数据存。,读写时序图中的ADDSETDATAST是通过不同的寄存器设置的。
       Bank1的有关寄存器:
       SRAM/NOR闪存片选控制寄存器FSMC_BCRx,该寄存器在这里用到第15EXTMOD、第13WREN[5:4]MWID[3:2]MTYP和最低位MBKEN
       EXTMOD扩展模式使能位,也就是是否允许接收读/写不同的时序。
       WREN写使能位。
       HWID[1:0]存储器数据总线宽度。008位,01:16位,1011保留。
       MTYP[1:0]存储器类型。00SRAMROM01PSRAM10NORFLASH11:保留。
MBKEN存储块使能位。
       SRAM存片选时/NOR序寄存器FSMC_BTRx,这个寄存器包含了每个存储块的控制信息,可以用于SRAMROMNOR闪存存储器。如果FSMC_BCRx寄存器中设置了EXTMOD位,则有两个时序寄存器分别对应读(本寄存器)和写操作(FSMC_BWTRx寄存器)。这里用到了[29:28]ACCMOD[15:8]DATAST[3:0]ADDSET
       ACCMOD[1:0]访问模式,00:访问模式A(用的)01:访问模式B;10~,11~
       DATAST[7:0]数据保持时间,0为保留设置,其他设置则代表保持时间为DATASTHCLK时钟周期。对于ILI9341来说,就是RD低电平持续时间,一般为355ns。一个HCLK时钟周期为13.8ns左右,为了兼容其他屏,这里设置DATAST15,也就是16HCLK时钟周期,时间大约是234ns(未计算数据存储的2HCLK时钟周期,对于9341来说是超频了,但实际上是可以正常使用的)。
       ADDSET[3:0]地址建立时间。其建立时间为ADDSETHCLK周期,最大为15HCLK周期。对于9341来说,这里相当于RD高电平持续时间,为90ns。本来这里应该设置和DATSAT一样,但是由于STM32F103FSMC的性能问题,就算设置ADDSET0RD的高电平持续时间要达到了190ns以上,这里设置ADDSET1,即2HCLK周期,实际RD高电平大于200ns
      
       SRAM/NOR闪写时序寄存器FSMC_BWTRx,用作写操作时序控制寄存器,需要用到的设置同样是ACCMODDATASTADDSET。设置方法同FSMC_BTRx一样,只是这里对应的是写操作的时序。对与ILI9341来说,高电平和低电平持续时间只需要15ns就够了。所以这里设置DATAST3,时间约为55nsADDSET(也存在性能问题)设置为0,实际WR高电平时间>100ns
       MDK的寄存器定义里面没有定义FSMC_BCRxFSMC_BTRxFSMC_BWTRx等单独的寄存器,而是将他们进行了一些组合。FSMC_BCRxFSMC_BTRx组合成BTCR的寄存器组,对应关系如下
BTCR[0]对应 FSMC_BCR1BTCR[1]对应FSMC_BTR1
BTCR[2]对应 FSMC_BCR2BTCR[3]对应FSMC_BTR2
BTCR[4]对应 FSMC_BCR3BTCR[5]对应FSMC_BTR3
BTCR[6]对应 FSMC_BCR4BTCR[7]对应FSMC_BTR4
FSMC_BWTRx 则组合成BWTR[7],他们的对应关系如下:
BWTR[0]对应 FSMC_BWTR1BWTR[2]对应FSMC_BWTR2
BWTR[4]对应 FSMC_BWTR3BWTR[6]对应FSMC_BWTR4
BWTR[1]BWTR[3]BWTR[5]保留,没有用到。
哈,又抄了好久的书。。。。。。。。是一个理解的过程吧,细细的精读。今天就先记这么多,明天来记库函数的相关配置,还有lcd有关函数的理解。明天也许会暂停一天,也不确定,有两个选修课的考试, ,还有一个ARM体系架构——上课讲的是原子的例程,用的是原子哥的PPT,考试了,准备带一本《原子教你玩STM32》去考试,哈哈!横扫一切。加油!不想因为这些影响学习的进程。
                                                               1127

回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-28 20:29:28 | 显示全部楼层
第九天TFTLCD显示实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
总结一下LCD的操作:
LCD初始化:
①   设置STM32LCD模块相连接的I/O口这里用到的是FSMC,所以需要这几个步骤
a)       GPIOFSMCAFIO时钟使能。
b)      GPIO初始化。
c)       FSMC初始化。
FSMC_NORSRAMInit()//初始化函数,只有一个参数,配置FSMC_BCRx寄存器
typedef struct
{
  uint32_t FSMC_Bank; //设置使用到的存储块标号和区号,FSMC_Bank1_NORSRAMx(这里x为4)
uint32_t FSMC_DataAddressMux//是否选择地址和数据复用数据线
uint32_t FSMC_MemoryType;//设置存储器类型
  uint32_t FSMC_MemoryDataWidth; //设置数据宽度
  uint32_t FSMC_BurstAccessMode;// 使能或关闭同步NOR闪存存储器的突发访问模式设置是否使用迸发访问模式(应该就是连续读写模式吧                                       
  uint32_t FSMC_AsynchronousWait;//设定是否使用异步等待信号   
  uint32_t FSMC_WaitSignalPolarity;//设置WAIT信号的有效电平
  uint32_t FSMC_WrapMode;//设置是否使用环回模式
  uint32_t FSMC_WaitSignalActive; //设置WAIT信号有效时机
  uint32_t FSMC_WriteOperation; //设置写使能
  uint32_t FSMC_WaitSignal;//设定是否使用WAIT信号  
  uint32_t FSMC_ExtendedMode; //扩展模式使能位
uint32_t FSMC_WriteBurst;//设定是否使用迸发写模式
FSMC_NORSRAMTimingInitTypeDef*FSMC_ReadWriteTimingStruct;//读时序参数变量  
FSMC_NORSRAMTimingInitTypeDef*FSMC_WriteTimingStruct;//写时序参数变量         
}FSMC_NORSRAMInitTypeDef;
typedefstruct
{
  uint32_t FSMC_AddressSetupTime; //地址建立时间
  uint32_t FSMC_AddressHoldTime;//地址保存时间   
  uint32_t FSMC_DataSetupTime;//数据保持时间    
  uint32_tFSMC_BusTurnAroundDuration;// BUSTURN 总线返转时间
  uint32_t FSMC_CLKDivision;//时钟分频
  uint32_t FSMC_DataLatency;//数据保存时间
  uint32_t FSMC_AccessMode;//访问模式
}FSMC_NORSRAMTimingInitTypeDef;
这个结构体用来设置FSMC/写时序
d)      FSMC使能
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAMx, ENABLE);
②   初始化LCD模块
一段初始化序列,由厂家提供。无需深究。
③   通过函数将字符和数字还有图形等显示到LCD
画点的基本流程:设置坐标—>GRAM指令—>GRAM
//LCD地址结构体
typedefstruct
{
    vu16 LCD_REG;//
    vu16 LCD_RAM;
}LCD_TypeDef;
//使用NOR/SRAMBank1.sector4,地址位HADDR[27,26]=11 A10作为数据命令区分线
//注意设置时STM32内部会右移一位对齐!                    
#define LCD_BASE       ((u32)(0x6C000000 |0x000007FE))
#defineLCD             ((LCD_TypeDef *)LCD_BASE)
LCD_BASE必须由外部电路的连接来确定,使用Bank.sector就是从0X6C000000开始,而0X000007FE则是A10的偏移量,将这个地址强制转化为LCD_TypeDef结构体地址,那么就可以得到LCD>LCD_REG的地址就是0X6C0007FE,对应的A10的状态位0(即RS=0),而LCD>LCD_RAM的地址就是0X6C000800(结构体自增),对应的A10的状态为1
  //LCD重要参数集(保存了一些LCD的重要参数信息)
typedef struct  
{                                                                        
       u16 width;                 //LCD 宽度
       u16height;                //LCD 高度
       u16 id;                       //LCD ID
       u8  dir;                     //横屏还是竖屏控制:0,竖屏;1,横屏。      
       u16 wramcmd;          //开始写gram指令
       u16  setxcmd;          //设置x坐标指令
       u16  setycmd;          //设置y坐标指令
}_lcd_dev;
CSWRRDI/O口方向都是由FSMC控制的,无需手动设置。
以下是基本的操作函数,设置光标位置和画点函数都在这些的基础上进行,有了这几个函数就可以结合LCD驱动的一些指令让LCD按自己意愿显示出各种各样的图案或者字符了。
//写寄存器函数
//regval:寄存器值
void LCD_WR_REG(u16 regval)
{   
   LCD->LCD_REG=regval;//写入要写的寄存器序号   
}
//LCD数据
//data:要写入的值
void LCD_WR_DATA(u16 data)
{   
   LCD->LCD_RAM=data;            
}
//LCD数据
//返回值:读到的值
u16 LCD_RD_DATA(void)
{
   vu16 ram;//防止被优化
   ram=LCD->LCD_RAM;      
   return ram;  
}                                
//写寄存器
//LCD_Reg:寄存器地址
//LCD_RegValue:要写入的数据
void LCD_WriteReg(u16LCD_Reg,u16 LCD_RegValue)
{  
   LCD->LCD_REG = LCD_Reg;//写入要写的寄存器序号  
   LCD->LCD_RAM = LCD_RegValue;//写入数据                   
}     
//读寄存器
//LCD_Reg:寄存器地址
//返回值:读到的数据
u16 LCD_ReadReg(u16 LCD_Reg)
{                                                                    
   LCD_WR_REG(LCD_Reg);//写入要读的寄存器序号
   delay_us(5);         
   return LCD_RD_DATA();//返回读到的值
}   
//开始写GRAM
voidLCD_WriteRAM_Prepare(void)
{
  LCD->LCD_REG=lcddev.wramcmd;        
}   
//LCDGRAM
//RGB_Code:颜色值
void LCD_WriteRAM(u16RGB_Code)
{                                                
   LCD->LCD_RAM = RGB_Code;//写十六位GRAM
}
历时三天,TFTLCD显示实验。虽然学习了LCD的有关操作,但是在FSMC上的学习还是不够,需要加以补充。
                                                                                                            1128

回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-29 21:13:12 | 显示全部楼层
第十天RTC实时时钟实验。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
要求:显示时间
STM32的实时时钟(RTC)是一个独立的定时器,拥有一组连续计数的计数器。RTC模块和时钟配置系统(RCC_BDCR寄存器)是在后备区域,即在系统复位或从待机模式唤醒后RTC的设置和时间维持不变。

RTC时钟配置的过程
①    使能电源时钟和备份区域时钟。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR,ENABLE);
②    取消备份区写保护。
PWR_BackupAccessCmd(ENABLE);//使能RTC和后备寄存器访问
③    复位备份区域,开启外部低速振荡器。
BKP_DeInit();//复位备份区域,不要每次都执行,视情况而定
       RCC_LSEConfig(RCC_LSE_ON);//开启外部低速振荡器
④    选择RTC时钟并使能。
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择RTC时钟
RCC_RTCCLKCmd(ENABLE);//使能
⑤    设置RTC分频,并配置RTC时钟,更新配置。
RTC预分频装载寄存器,有两个,RTC_PRLH和RTC_PRLL,RTC_PRLH只有第四位有效,来储存RTC_PRLL的[19:16]再加上RTC_PRLL的16位为RTC时钟的分频数。
         RTC预分频器余数寄存器RTC_DIVHRTC_DIVL,用于获得比秒钟更精确的时钟,各位含义和RTC预分频装载寄存器一样。

RTC_SetPrescaler(32767);//设置RTC时钟的分频数
设置分频数后需等待RTC寄存器操作完成并同步后再开始配置
       RTC_WaitForLastTask();等待RTC寄存器写操作完成
              RTC_EnterConfigMode();允许配置
   RTC_CRL位5,PTOFF—操作关闭位,只读,0:上一次对RTC寄存器的写操作仍在进行,此时无法对任何RTC寄存器进行写操作;1:已经完成。
  RTC计数器寄存器RTC_CNT,两个寄存器共32位,用于记录秒钟。

              允许配置后,进行配置,设置时间。
              RTC_ExitConfigMode();//退出配置,更新配置

RTC_CRL位4,CNF—配置标志,由软件配置;0:退出配置模式,开始更新RTC寄存器;1:进入配置模式。
RTC_CRL位3,RSF—寄存器同步标志,每当RTC_CNT和RTC_DIV寄存器由软件更新或清‘0’时,此位由硬件置1。在APB1复位或停止后,此位必须由软件清0。要进行任何读操作之前,用户程序必须等待此位被硬件置1,以确保PTC_ALR、PTC_CNT和PTC_PRL已经同步。
⑥    标识初始化完成,设置秒中断允许,RTC使能中断,设置中断分组。
RTC控制寄存器RTC_CRH和RTC_CRL(16位)
RTC_CRH:位2—OW1E允许溢出中断位;位1—允许闹钟中断位;     位0:允许秒中断位
RTC_CRL位0:SECF—秒标志,由硬件置1,同时RTC计数器加1,如果RTC_CRH寄存器的SECIE=1,则产生中断由软件清楚,0:秒标志条件不成立;1:成立。
BKP_WriteBackupRegister(BKP_DR1,0x5050);//表示已经初始化过了
              RTC_ITConfig(RTC_IT_SEC,ENABLE);//设置秒中断允许,RTC使能中断
NVIC_Init();//设置中断分组
⑦    编写中断服务函数
void RTC_IRQHandler(void)
RTC_CRL位1:ALRF—闹钟标志,0:无闹钟;1:有闹钟。由硬件置1,软件置0。
RTC_CRL位2:OWF—溢出标志,由硬件置1,软件置0。
RTC闹钟寄存器RTC_ALRH和RTC_ALRL共32位,用来标记闹钟产生的时间(以秒为单位)。如果RTC_CNT和RTC_ALR的值相等,且使能了中断,则会产生一个闹钟中断。进入配置模式才能修改寄存器的值。
其它一些寄存器:
STM32的备份寄存器,4216位的寄存器,,可用来存储84个字节的用户程序数据。
BKP控制寄存器用来管理侵入检测和RTC校准功能。(1)通过设置寄存器RCCAPB1ENRPWRENBKPEN位来打开电源和后备接口的时钟。(2)电源控制器(PWR_CR)的DBP位来使能对后备寄存器和RTC的访问。一般用BKP来存储RTC的校验值或者记录一些重要数据
备份区域控制寄存器RCC_BDCR32位),位16BDRET—备份域软件复位;位15RTC时钟使能;[9:8]RTCSELRTC时钟源选择,直到下次后备域被复位,它不能再被改变,可通过BDRST清楚;位2LSEBYP—外部低速时钟振荡器旁路,只有在外部32KHZ振荡器关闭时,才能写入;位1LSERDY—外部低速LSE就绪,在LSEON被清零后,该位需要6个外部低速振荡器的周期才被清零;位0LSEON—外部低速振荡器使能。
库文件:stm32f10x_rtcstm32f10x_bkp
关于USMART调试组件,并没有越过,把它作为有用工具来使用就好了,很六。。。。
                                                                                                                   1029

回复 支持 反对

使用道具 举报

1

主题

19

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2016-9-11
在线时间
12 小时
发表于 2016-10-29 22:50:11 | 显示全部楼层
哈哈 。看来都是这样。我刚开始学的时候完全照葫芦画瓢。 出了问题找不到方向。才想起来从头再来一遍
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-30 20:28:07 | 显示全部楼层
[size=18.6667px]第十一天待机唤醒实验。。。。。。。。。。。。。。。。

要求:在上一个实验的基础上,利用WK_UP按键来实现唤醒和进入待机模式的功能。

STM32的低功耗模式有三种:睡眠模式(CortexM3内核停止,外设仍然运行)、停止模式(所有时钟都停止)、待机模式(1.8V内核电源关闭)。
睡眠模式:CPU始终关闭,对其它时钟和ADC时钟无影响,电压调节器开,进入操作有两种—WFI(任意中断都能唤醒)或WFE(唤醒事件)。

停机模式:所有使用1.8V的区域的时钟都已关闭,HSIHSE振荡器关闭,在低功耗模式下可进行开/关设置电压调节器,进入操作—PDDSLPDS+SLEEPDEEP+WFIWFE(唤醒:任一外部中断,在外部寄存器中设置)。

待机模式:所有使用1.8V的区域的时钟都已关闭,HSIHSE振荡器关闭,电压调节器关,进入操作—PDDS+SLEEPDEEP+WFIWFE(唤醒:WKUP引脚的上升沿、RTC警告事件、NRST引脚上的外部复位、IWDG复位。)待机模式唤醒后,除了电源控制/状态寄存器,所有寄存器被复位。

功耗的大小:睡眠>停机>待机。


电源控制寄存器PWR_CR,位8DBP:取消后备区域的写保护;位3CSBF:清除待机位,始终读0,写0无效,写1清除;位2—清楚唤醒位:始终读0,写12个系统时钟周期后清楚WUF唤醒位;位1PDDS:(掉电深睡眠,0:当CPU进入深睡眠时进入停机模式,调压器的状态由LPDS控制,1:CPU进入深睡眠时进入待机模式。)

电源控制/状态寄存器PWR_CSR,位8EWUP,使能WKUP引脚:(0WKUP引脚为通用I/O1WKUP引脚用于唤醒,,被强制为输入下拉的配置,在系统复位时清除这一位;)位2PVDOPVD输出;位1SBF,待机标志,由硬件设置;位0WUF;唤醒标志,有硬件设置,WKUP引脚已经是高电平时,在使能WKUP引脚(通过设置EWUP位)时,会检测到一个额外的事件。
进入待机模式的过程:
①    使能电源时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
②    设置WK_UP按键作为唤醒源
PWR_WakeUpPinCmd(ENABLE);
③    设置SLEEPDEEP位、PDDS位,执行WFI指令,进入待机模式
PWR_EnterSTANDBYMode();
④    因为要通过中断来唤醒CPU,所以设置一下中断函数、中断分组
设置PA0WK_UP)—中断线0
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
EXTI_Init();//中断初始化
NVIC_Init();//初始化NVIC
GPIO_Init();//GPIO初始化
⑤    编写中断函数
在这里进入待机模式

使用的固件库文件stm32f10x_pwr

                                                                                                             1030

回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2016-8-25
在线时间
0 小时
发表于 2016-10-30 20:40:47 | 显示全部楼层
不错  同是初学者 感觉你的总结比我的清晰多了
回复 支持 反对

使用道具 举报

7

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2016-8-24
在线时间
62 小时
 楼主| 发表于 2016-10-30 21:48:56 来自手机 | 显示全部楼层
天山懒人 发表于 2016-10-30 20:40
不错  同是初学者 感觉你的总结比我的清晰多了

我只是把书上的内容摘抄在这里,细心一点,都可以的
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-26 17:07

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表