OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
楼主: 龙之谷

菜鸟开帖,持续更新90天,顺序学习开发板大部分实验,以此帖作为一个坚持的动力

  [复制链接]

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-22 23:34:54 | 显示全部楼层
回复【200楼】龙之谷:
---------------------------------
谢谢分享,第200个回复是我的了,哈哈。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
正点原子逻辑分析仪DL16劲爆上市
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-23 00:19:13 | 显示全部楼层
回复【201楼】正点原子:
---------------------------------
老大真欢乐啊

话说老大这触屏程序闹了多长时间,今天抄了半天一个touch.c文件没抄完
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-23 10:17:31 | 显示全部楼层
回复【202楼】龙之谷:
---------------------------------
这是慢慢改进的过程,从最早的mini板到战舰板,再到支持电容屏,兼容各种电容屏...
经过了N代了。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-23 23:42:14 | 显示全部楼层
2015年08月23日 23:48:57,下个雨停电停到现在,简直无语
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-23 23:43:49 | 显示全部楼层
第三三天  2015年08月23日  周日     例程:触摸屏实验(二)

一、结构体中包含函数指针成员的运用
[mw_shl_code=c,true]typedef struct //触摸屏控制器 { u8 (*init)(void); //初始化触摸屏控制器 u8 (*scan)(u8); //扫描触摸屏,0--屏幕扫描,1--物理坐标 void (*adjust)(void); //触摸屏校准 ...//此处省略其他常用类型如整型等变量定义[/mw_shl_code] [mw_shl_code=c,true]      uchar n;[/mw_shl_code] [mw_shl_code=c,true]}_m_tp_dev; extern _m_tp_dev tp_dev; //触屏控制器在touch.c里面定义[/mw_shl_code]
1.函数指针是指向函数的指针变量,其实质是指针变量。指向函数的指针包含了函数的地址,可以用它来调用函数,声明格式如
          类型说明符 (*函数名)(参数)

2.把函数地址赋给函数指针以及通过指针调用函数有两种方式,假设函数指针ptr,函数定义uchar function(void);

第一种方式:ptr = &function     x = (*ptr)();
第二种方式:ptr = function       x = ptr();
第二种格式看上去和函数调用无异,但有些程序员倾向于第一种格式,因为它明确指出是指针而非函数名来调用函数的。开发指南中使用的是第二种调用方式。

3.定义结构体变量以后对其进行了初始化,如下
[mw_shl_code=c,true]_m_tp_dev tp_dev = { TP_Init, TP_Scan, TP_Adjust, ... };[/mw_shl_code]
通过第二种将函数名直接赋值给函数指针,其中TP_Init和TP_Adjust都是单独定义的函数,我们只需要在对应结果体变量后加括号分号();即等于调用了函数,如初始化函数定义为u8 TP_Init(void)在主函数中进行了调用tp_dev.init();就将结构体中函数指针成员与函数进行了巧妙结合,便于管理。
而结构体中函数指针成员scan则更加体现了此中便利性,根据不同情况对其进行不同扫描函数的赋值,使其指向不同的函数。初始化时将其赋值给函数定义为u8 TP_Scan(u8 tp);的电阻触摸按键扫描,而当检测到是电容触屏时根据电容屏型号分别赋值
9147型号:tp_dev.scan = GT9147_Scan----->[其中函数定义为u8 GT9147_Scan(u8 mode);]
2001型号:tp_dev.scan = OTT2001A_Scan----->[其中函数定义u8 OTT2001A_Scan(u8 mode);]
提供了程序间的兼容通道,程序总体统一协调。


4.通过以上,我们以后可将某一文件中常用函数通过结构体中函数指针进行衔接,
调用函数时直接对结构体成员进行处理即可,合理利用可使程序更加清晰整齐,便于管理与维护。

二、触屏校准

1.屏幕显示两种定位系统:

相对定位系统,只和前一次位置坐标有关,如传统鼠标。
绝对坐标系统,每次定位坐标与上一次定位坐标没有关系,每次触摸的数据通过校准转为屏幕上的坐标,触屏这套坐标在同一点的输出数据是稳定的,如触摸屏。

2.漂移,由于技术原理的原因,并不能保证同一点触摸每一次采样数据都相同,不能保证绝对坐标定位,这就是触屏最怕出现的漂移问题。所以很多触屏系统启动后,进入应用程序前,先要执行校准程序。


3.应用程序中LCD坐标是以像素为单位的;而
从触屏读出的是点的物理坐标。比如说物理坐标的10cm可以是容纳了100个像素也可以是200个像素,只要两者都确定则可通过它们之间的线型关系进行相互转化。

4.校正思路如下



参考链接
【1】http://blog.csdn.net/htyurencaotang/article/details/11490081

以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-24 01:13:08 | 显示全部楼层
现在时间2015年08月24日 01:19:54,洗澡睡觉,希望今天不要迟到...
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-24 23:18:58 | 显示全部楼层
第三四天  2015年08月24日  周一     例程:红外遥控式样



1.红外遥控不具有像无线电遥控那样穿过障碍物去控制被控对象的能力,且为不可见光,对环境影响很小,波动波长远小于无线电波长,所以红外遥控不会影响其他家用电气,也不会影响临近的无线电设备。


2.红外遥控编码最广泛应用分两种:NEC Protocol的PWM(脉冲宽度调制)和Philips RC-5 Protocol的PPM(脉冲位置调制)。


3.NEC协议特征:8位地址和8位指令长度;地址和命令2次传输;PWM脉冲位置调制,以发射红外载波的占空比代表“0”和“1”;载波频率位38Khz

;位时间位1.125ms或2.25ms。

4.NEC遥控指令数据格式:同步码头、地址码、地址反码、控制码、控制反码。

同步码:9ms低电平+4.5ms高电平
逻辑“1”:560us低电平+1680us高电平
逻辑“0”:560us低电平+  560us高电平
连发码:9ms低电平+2.5ms高电平+0.56ms高电平+97.94ms高电平。(在一帧数据发送完毕后,按键没有放开,则发射重复码,即连发码)。

5.TIM1是高级定时器,有2个中断服务函数:

TIM1_UP_TIM10_IRQHandler();用于处理TIM1溢出事件,标记键值获取完成以及按键松开清零按下次数
TIM_CC_IRQHandler();用于处理TIM1输入捕获事件,实现对红外信号的高电平脉冲捕获。
两个中断函数中,第一个处理溢出事件不是必须的,可以通过在第二个输入捕获中断中添加适当处理进行取代,取代后中断中由于松开后没有下降沿,所以无法检测到按键松开清零,所以每次在松开按键后屏幕保持最后一次按下键按下次数【具体实现见附件】。如果松开按键后需要对按下次数进行清零,可以在主函数中进行延时判断,如果1s延时后按键按下次数没有变化,则视为松开按键,可以清零按下次数,从而与开发指南源程序效果一直。



触摸屏实验(三)

//SPI通信
1.void TP_Write_Byte(u8 num);-----SPI写数据,向触摸屏IC写入1byte数据 
2.u16 TP_Read_AD(u8 CMD);-----SPI读数据,从触摸屏IC读取值

//直接写入读取坐标命令读出X、Y坐标
3.u16 TP_Read_XOY(u8 xy);-----读取一个坐标值(x或者y),连续读取READ_TIMES次数据,对这些数据升序排列,然后去掉最低和最高LOST_VAL个数,取平均值 
4.u8 TP_Read_XY(u16 *x, u16 *y);-----读取x,y坐标
5.u8 TP_Read_XY2(u16 *x, u16 *y);-----连续2次读取触摸屏IC,且这两次的偏差不能超过ERR_RANGE,满足条件,则认为读数正确,否则读数错误

//画点函数,涉及一些画图小算法
6.void TP_Drow_Touch_Point(u16 x, u16 y, u16 color);-----与LCD部分有关的函数,画一个触摸点,用来校准用的
7.void TP_Draw_Big_Point(u16 x, u16 y, u16 color);-----与LCD部分有关的函数,画一个大点(2*2的点)

//读出X、Y坐标并进行简单换算
8.u8 TP_Scan(u8 tp);-----触摸按键扫描

//EEPROM读写操作
9.void TP_Save_Adjdata(void);-----保存校准参数,保存在EEPROM里面的地址区间基址
10.u8 TP_Get_Adjdata(void);-----得到保存在EEPROM里面的校准值

//提示字符,仅显示一些实时信息
11.void TP_Adj_Info_Show(u16 x0, u16 y0, u16 x1, u16 y1, u16 x2, u16 y2, u16 x3, u16 y3, u16 fac);-----提示字符串

//校准函数,该段程序较长,运用四边形的简单几何关系进行计算得到校准参数作为以后操作的基础
12.void TP_Adjust(void);-----触摸屏校准代码,得到四个校准参数

//触屏初始化,即一般初始化过程
13.u8 TP_Init(void);-----触摸屏初始化


通过以上简单归类分析,触屏貌似高端复杂,实际过程也并没有太大难度,最大门槛应该是对寄存器的熟悉、简单算法的选取及相关参数(如误差范围)的把握方面,具体到与单片机的交互上厂家已经将其简化到了很简洁的程度。

remote.c

4.05 KB, 下载次数: 595

以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-25 00:11:54 | 显示全部楼层
回复【205楼】龙之谷:
---------------------------------
顶。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-25 00:12:05 | 显示全部楼层
回复【207楼】龙之谷:
---------------------------------
继续顶。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-25 22:44:43 | 显示全部楼层
今天的呢???
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-25 23:04:41 | 显示全部楼层
第三五天  2015年08月25日  周二     例程:DS18B20温度传感器实验  (AND)  DHT11温湿度传感器实验

一、DS18B20

1.DS18B20是由DALLAS半导体公司推出的一种“一线总线”接口的温度传感器。

2.测量温度范围-55℃到+125℃,精度为正负0.5℃。工作电压范围3~5.5V。

3.自带ROM中64位序列号是出厂前被光记好的,可以看作是其地址序列码,排列是8位产品家族码+48位序列号+8位循环冗余校验码。ROM作用是每个DS18B20各不相同,这样可以一根总线挂接多个DS18B20。数据传输过程中低位先出。

二、DHT11

1.DHT11是一款温湿度一体化的数字传感器,包括一个电阻时测试元件和一个NTC测温元件,通过单片机等微处理器简单的电路连接就能够实时采集本地温度和湿度。

2.DHT11与单片机通过单总线进行通信,只需要一个IO口。

3.功耗    :5V电源电压下,平均最大电流0.5mA。
  工作电压:3.3~5V
  测量范围:湿度20~90%,温度0~50℃
  精度    :湿度正负5%,温度正负2℃
  分辨率  :湿度1%,温度1℃

4.DHT11传感器内部温度和湿度数据40bit的数据一次性给单片机,采用校验和方式进行校验。高位先出,数据包括
8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和。输出的数据时未编码的二进制数据,各个字节间应分开处理。

5.DHT11和MCU一次通信最大3ms左右,建议主机连续读取时间间隔不要小于100ms。

6.数据发送流程



数字‘0’时序



数字‘1’时序



读取一个位程序
[mw_shl_code=c,true] /************************************************ 功能 :读取一个位 ******************************************************/ u8 DHT11_Read_Bit(void) { u8 retry; while(DHT11_DQ_IN && retry < 100) { retry++; delay_us(1); } retry = 0; while(!DHT11_DQ_IN && retry < 100) { retry++; delay_us(1); } delay_us(40); if(DHT11_DQ_IN) { return 1; } return 0; }[/mw_shl_code]
程序处理清晰明了,在把握时序基础上通过判断有效位高电平时长来得出传输位的值。
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-25 23:07:46 | 显示全部楼层
回复【210楼】正点原子:
---------------------------------
今天的缩水有点严重...
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-26 23:43:12 | 显示全部楼层
第三六天  2015年08月26日  周三     例程:MPU6050传感器实验


1.MPU6050,六轴传感器(三轴加速度+三轴角速度(陀螺仪))。是InvenSense公司推出的全球首款整合性6轴运动处理组件。
2.MPU6050含有第二IIC接口,可用于连接外部磁力传感器(实现9轴),利用自带数字运动处理器(DMPigital Motion Processo)硬件加速引擎,通过主IIC接口,向应用输出完整9轴融合演算数据。
3.有了DMP,可以使用InvenSense公司提供的运动处理资料库,非常方便的实现姿态解算,降低运动处理运算对操作系统的负荷,同时降低开发难度。
4.VDD供电电压为2.5V、3.0V、3.3V(正负5%)。VLOGIC可低至1.8V(正负5%)。
5.陀螺仪工作电流5mA,待机电流5uA;加速度工作电流500uA,省电模式电流40uA@10Hz。
6.高达400Khz的IIC通信。

7.对于初学者,期望得到的时姿态数据,即欧拉角:航向角(yaw)、横滚角(roll)、俯仰角(pitch)。有了这三个角,就可以得到当前四轴的姿态。
8.利用原始数据来得到欧拉角数据的过程比较复杂,DMP提供了MPU6050的嵌入式驱动库,据此,可以将原始数据直接转换成四元数输出,得到四元数以后,就可以很方便的算出欧拉角。使用DMP大大简化了四轴的代码设计。
9.q30是一个常数,1073741824,即2的30次方。



学渣如我,看到欧拉各种角、各种计算公式,犹如一个小学生需要学习高三知识一样,各种不懂。六轴效果纵然炫酷,个人能力有限、工作一时涉及不到,也就无需在此多做进一步学习,但我们可以从程序中总结一些单片机与外部元器件沟通的环节,即单片机通过IIC、SPI等通信方式对外部元器件寄存器进行读写来实现外部元器件的功能。

本实验是利用IIC进行通信,我们以IIC与MPU6050进行寄存器读写的过程来进行分析

1.我们以单片机向MPU6050寄存器写入数据函数来逆推:
①具体某一写入函数如下
[mw_shl_code=c,true]/**************************************************** 功能 :设置MPU6050陀螺仪传感器满量程范围 //fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps //返回值:0,设置成功 其他,设置失败 *********************************************************/ u8 MPU_Set_Gyro_Fsr(u8 fsr) { return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围 }[/mw_shl_code]
②从上可以看出,写入寄存器函数直接调用写字节函数然后根据写入是否成功返回值,写入字节函数如下
[mw_shl_code=c,true]/********************************************************************* 功能 :MPU写一个字节 //reg:寄存器地址 //data:数据 //返回值:0,正常 其他,错误代码 ********************************************************************************************/ u8 MPU_Write_Byte(u8 reg,u8 data) { IIC_Start(); IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令 if(IIC_Wait_Ack()) //等待应答 { IIC_Stop(); return 1; } IIC_Send_Byte(reg); //写寄存器地址 IIC_Wait_Ack(); //等待应答 IIC_Send_Byte(data);//发送数据 if(IIC_Wait_Ack()) //等待ACK { IIC_Stop(); return 1; } IIC_Stop(); return 0; }[/mw_shl_code]
其过程主要是:开始IIC--发送地址、写命令--(应答)--写寄存器地址--(应答)--写数据--(应答)--结束IIC。其中主要函数是发送字节函数。

③发送字节函数如下
[mw_shl_code=c,true]/********************************************************************* 功能 :发送一个字节 ********************************************************************************************/ void IIC_Send_Byte(u8 txd) { u8 t; SDA_OUT(); IIC_SCL = 0; for(t=0; t<8; t++) { IIC_SDA = (txd & 0x80) >> 7; txd <<= 1; delay_us(2); IIC_SCL = 1; delay_us(2); IIC_SCL = 0; delay_us(2); } }[/mw_shl_code]
此时,我们会发现这个写入字节函数就是简单的IIC通信函数,通过以上三步,基本完成了单片机对MPU6050寄存器的写入。

2.通过以上分析,基本了解了写入外部元器件寄存器的逆推过程,下面我们可以通过以上经验来试着组建从IIC通信函数到读出寄存器的过程,也就是顺推:
①IIC通信读取字节函数
[mw_shl_code=c,true]/********************************************************************* 功能 :读一个字节, ack=1发送ACK ********************************************************************************************/ u8 IIC_Read_Byte(uchar ack) { uchar i, receive = 0; SDA_IN(); for(i=0; i<8; i++) { IIC_SCL = 0; delay_us(2); IIC_SCL = 1; receive <<= 1; if(READ_SDA) { receive++; } delay_us(1); } if(!ack) { IIC_NAck(); } else { IIC_Ack(); } return receive; }[/mw_shl_code]
②下一步,我们应该需要根据IIC元器件读取过程来读取寄存器,故此处需要一个元器件(MPU6050)读取字节函数,如下
[mw_shl_code=c,true]/********************************************************************* 功能 :MPU读一个字节 //reg:寄存器地址 //返回值:读到的数据 ********************************************************************************************/ u8 MPU_Read_Byte(u8 reg) { u8 res; IIC_Start(); IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令 IIC_Wait_Ack(); //等待应答 IIC_Send_Byte(reg); //写寄存器地址 IIC_Wait_Ack(); //等待应答 IIC_Start(); IIC_Send_Byte((MPU_ADDR<<1)|1);//发送器件地址+读命令 IIC_Wait_Ack(); //等待应答 res=IIC_Read_Byte(0);//读取数据,发送nACK IIC_Stop(); //产生一个停止条件 return res; }[/mw_shl_code]
③现在底层已经建立完成,我们只需要在具体读取函数中调用MPU读字节函数即可,如下
[mw_shl_code=c,true]/********************************************************************* 功能 :得到陀螺仪值(原始值) //gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号) //返回值:0,成功 其他,错误代码 ********************************************************************************************/ u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz) { u8 buf[6],res; res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf); if(res==0) { *gx=((u16)buf[0]<<8)|buf[1]; *gy=((u16)buf[2]<<8)|buf[3]; *gz=((u16)buf[4]<<8)|buf[5]; } return res;; }[/mw_shl_code]
【注】MPU_Read_Len()函数与MPU_Read_Byte()函数基本类似,故在此代替使用。

3.进一步分析,单片机与外部元器件如MPU6050通信过程只需要两步:其一,建立IIC通信基础函数;其二,根据元器件寄存器读写过程(参考对应数据手册)建立写入寄存器、读出寄存器函数。而对于某一具体读写寄存器函数则是直接调用第二步所实现的函数。

以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-27 22:36:28 | 显示全部楼层
第三七天  2015年08月27日  周四     例程:NRF24L01无线通信实验

一、基础知识
1.NRF24L01使用2.4G全球开放的ISM频段,最高工作速率2Mbps,高效的GFSK调制,抗干扰能力强。125个可选频道,满足多点通信和调频通信的需要。

2.NRF24L01通过SPI与外部MCU通信,最大的SPI速度可达10Mhz。

3.NRF24L01每次最多传输32个字节。

4.2.4G无线技术,因其频段处于2.405GHz~2.485GHz之间。此频段是国际规定的免费频段。


二、读写寄存器过程

1.写寄存器,先实现SPI读写函数
[mw_shl_code=c,true]/********************************************************************* 功能 :SPI读写函数 ********************************************************************************************/ u8 SPI1_ReadWriteByte(u8 TxData) { while((SPI1->SR & 1 << 1) == 0); SPI1->DR = TxData; while((SPI1->SR & 1 << 0) == 0); return SPI1->DR; }[/mw_shl_code]

在读写函数基础上,对寄存器进行写入
[mw_shl_code=c,true]/********************************************************************* 功能 :SPI写寄存器 //reg:指定寄存器地址 //value:写入的值 ********************************************************************************************/ u8 NRF24L01_Write_Reg(u8 reg, u8 value) { u8 status; NRF24L01_CSN = 0; status = SPI1_ReadWriteByte(reg); SPI1_ReadWriteByte(value); NRF24L01_CSN = 1; return(status); }[/mw_shl_code]

2.读寄存器,同样在SPI读写函数寄存器基础上,进行寄存器读操作
[mw_shl_code=c,true]/********************************************************************* 功能 :读取SPI寄存器值 //reg:要读的寄存器 ********************************************************************************************/ u8 NRF24L01_Read_Reg(u8 reg) { u8 value; NRF24L01_CSN = 0; SPI1_ReadWriteByte(reg); value = SPI1_ReadWriteByte(0xff); NRF24L01_CSN = 1; return(value); }[/mw_shl_code]

以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-27 23:18:19 | 显示全部楼层
回复【214楼】龙之谷:
---------------------------------
继续顶起
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-28 23:34:47 | 显示全部楼层
第三八天  2015年08月28日  周五     例程:FLASH模拟EEPROM实验

1.STM32F407ZGT6的FLASH容量为1024K字节。

2.大容量产品闪存模块组织图(STM32F407ZGT6)



闪存模块分为主存储器、系统存储器、OPT区域和选项字节等四部分。

     2.1.主存储器-----存放代码和数据常数
                   -----分为12个扇区(4*16KB + 1*64KB + 7*128KB
                   -----主存储器起始地址是0X08000000,B0、B1都接GND的时候,就是从0X08000000开始运行代码
     2.2.系统存储器-----主要存放bootloader代码,出厂时就固化在里面了,专门来给主存储器下载代码
                   -----当B0接3.3V,B1接GND的时候,从该存储器启动(即进入串口下载模式)
     2.3.OTP区域-----一次性可编程区域,共528字节(16*32Byte + 16Byte)
                   -----前16*32Byte可以用来存储一些用户数据(一次性可编程,见【注1】);后16Byte用于锁定对应块
     2.4.选项字节-----配置读保护、BOR级别、软件/硬件看门狗以及器件处于待机或停止模式下的复位

3.闪存存储器接口寄存器用于控制闪存读写等操作,是整个闪存模块的控制机构。


4.STM32F4的FLASH读取是比较简单。我们要从地址addr读取一个字,可以通过data = *(vu32*)addr;实现,将addr强制转换为vu32指针,然后读取指针所指向的地址的值,即得到了addr地址的值。类似的,将vu32改为u8即可读取地址的一个字节。


5.STM32F4的FLASH写入主要需注意两点,其一,写入地址的FLASH是被擦出了的,即0xffffffff;其二,写/擦除操作期间不能从FLASH中执行代码或数据读取操作。写操作过程如下

     5.1.检查FLASH_SR中断BSY位,确保当前未执行任何FLASH操作
     5.2.将FLASH_CR寄存器中断PG位置一,激活FLASH编程
     5.3.针对所需存储器地址执行数据写入
     5.4.等待BSY位清零,即完成一次编程

6.STM32F4闪存擦除分两种:扇区擦除和整片擦除。第一种扇区擦除步骤如下

     6.1.检查FLASH_CR的LOCK,如果没有解锁先进行解锁
     6.2.检查FLASH_SR寄存器的BSY位,确保当前未执行任何FLASH操作
     6.3.在FLASH_CR寄存器中,将SER置一,并从主存储块的12个扇区中选择要擦除的扇区SNB
     6.4.将FLASH_CR寄存器中的STRT位置一,触发擦除操作
     6.5.等待BSY位清零

7.个人认为,在进行写入指定长度数据函数中,判断语句if(addrx<0x1fff0000)//只有主存储区,才能执行擦除操作!!应该改为if(endaddr<0x1fff0000),其中addrx是写入起始地址,endaddr是写入结束地址,应该是写入的每个字节都不能超过主存储区而非起始地址,故认为开发指南中此处略有失误,而此错误在大多数测试情况下是不会体现出来的。

【注1】关于OTP区域一次性可编程详解





相关链接
老大测试FLASH编程时遇到的问题及解决过程:http://www.openedv.com/posts/list/24177.htm

以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-29 00:40:10 | 显示全部楼层
回复【216楼】龙之谷:
---------------------------------
顶,快一半了,呵呵
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2015-8-28
在线时间
3 小时
发表于 2015-8-29 09:41:53 | 显示全部楼层
楼主,是否可以帮我做一个测试软件,使用到如下功能:
串口1发送和接收简单数据
SPI1发送数据
SPI2接收数据
IIC1发送数据
TIM8、9输出时钟
32*32定点乘
128+64定点加
双精度浮点数乘、加、开平方

可出少量费用
回复 支持 反对

使用道具 举报

3

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2015-8-28
在线时间
3 小时
发表于 2015-8-29 09:43:05 | 显示全部楼层
回复【218楼】laonong:
---------------------------------
是STM32F405,硬件已做好。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-29 20:45:56 | 显示全部楼层
回复【217楼】正点原子:
---------------------------------
有点麻木了,坚持下去的阻力不大,动力也不是很大,呵呵,希望这个阶段早点过去
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-29 20:54:49 | 显示全部楼层
回复【218楼】laonong:
---------------------------------
可以发帖子找人做一下,这几个功能组合到一起也挺有趣的

我也想着以后接活,但现在晚上更新帖子再稍玩会就没剩多少时间,自己F4也是学习中,接了你的在完成时间、完成质量上都是对你我的不负责

在更新完此帖前不会进行其他工作以外的“任务”,希望自己能真正静下来

共同进步,祝顺利!
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-29 22:44:32 | 显示全部楼层
第三九天  2015年08月29日  周六     例程:摄像头实验



1.OV2640是OV(OmniVision)公司生产的一颗1/4寸的CMOS UXGA(1632*1232
)图像传感器。

2.可以通过标准SCCB(控制图像传感器芯片的运行)接口,兼容IIC接口。


3.OV2640常见设置关系:传感器窗口设置>图像尺寸设置>图像窗口设置>=图像输出大小设置。


4.UXGA即分辨率为1600*1200的输出格式,类似的还有:SXGA(1280*1024),WXGA+(1440*900),XVGA(1280*960),
WXGA(1280*800),XGA(1024*768
),SVGA(800*600),VGA(640*480),CIF(352*288),WQVGA(400*240),QCIF(176*144),
QQVGA(160*120)等。


5.PCKL,即像素时钟,一个PCLK时钟,输出一个像素(或半个像素)

  VSYNC,即帧同步信号
  HREF/HSYNC,即行同步信号

6.DCMI即数字摄像头接口,是一个同步并行接口,能够接收外部8位、10位、12位、14位CMOS摄像头模块发出的高速(可达54MB/s)数据流。



本节多次用到2维数组,存放初始化序列寄存器及对应的值,这点对如我等见少识窄者来说就像一层窗户纸,现在我们看看具体实现过程。

1.首先当然定义一个二位数组,第一个下标表示该数组所配置总寄存器数目,第二个下标为2(一个具体寄存器+相应配置),如ov2640cfg.h中
[mw_shl_code=c,true]const u8 ov2640_yuv422_reg_tbl[][2]= { 0xFF, 0x00, 0xDA, 0x10, 0xD7, 0x03, 0xDF, 0x00, 0x33, 0x80, 0x3C, 0x40, 0xe1, 0x77, 0x00, 0x00, };[/mw_shl_code]
2.编写写寄存器函数,至少需要两个参数,一个是传入寄存器,另一个传入配置数据,如sccb.c中
[mw_shl_code=c,true]//写寄存器 //返回值:0,成功;1,失败. u8 SCCB_WR_Reg(u8 reg,u8 data) { u8 res=0; SCCB_Start(); //启动SCCB传输 if(SCCB_WR_Byte(SCCB_ID))res=1; //写器件ID delay_us(100); if(SCCB_WR_Byte(reg))res=1; //写寄存器地址 delay_us(100); if(SCCB_WR_Byte(data))res=1; //写数据 SCCB_Stop(); return res; }[/mw_shl_code]
3.将以上两个进行组合,通过一一对应进行正确赋值,如ov2640.c中
[mw_shl_code=c,true]//OV2640切换为JPEG模式 void OV2640_JPEG_Mode(void) { u16 i=0; //设置:YUV422格式 for(i=0;i<(sizeof(ov2640_yuv422_reg_tbl)/2);i++) { SCCB_WR_Reg(ov2640_yuv422_reg_tbl[0],ov2640_yuv422_reg_tbl[1]); } //设置:输出JPEG数据 for(i=0;i<(sizeof(ov2640_jpeg_reg_tbl)/2);i++) { SCCB_WR_Reg(ov2640_jpeg_reg_tbl[0],ov2640_jpeg_reg_tbl[1]); } }[/mw_shl_code]
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-30 13:52:42 | 显示全部楼层
第四十天  2015年08月30日  周日     例程:外部SRAM实验



1.STM32F407ZGT6自带192K字节的SRAM。

2.开发板板载IS62WV51216,即1M字节容量SRAM芯片。

2.IS62WV51216是ISSI(Intergrated Silicon Solution,Inc)公司生产的一颗16位宽512K(512*16,即1M字节)容量的CMOS静态内存芯片。具有45ns/55ns的高速访问速度。

4.在IS62WV512连接中,它的A[0:18]并不是顺序连接到STM32F4的FMSC_A[0:18],这不影响正常使用外部SRAM,因为地址具有唯一性。也就是说你只要给每单位存储区定下地址且彼此互不相同,按照自己定义的地址规则读写即可。可以以三个柜子放东西为例,三个柜子从左向右依次命名1、2、3,依次存放上衣、裤子、鞋子。也可依次命名1、3、2,柜子从左到右存放顺序不变,此时标号3存放裤子,以后放裤子/拿裤子直接找3号柜子即可。当然你还可以给柜子分别命名吃、饭、了,给事物命名是意识形态,(彼此独立的)本质不会因为命名而改变。而数据线必须一一对应连接的原因可能是UB、LB分别是高字节控制和低字节控制信号,也就是高低字节是可以分别操作的。

5.定义一个超大数组testsram,并指定该数组定义在外部sram起始地址(__attribute__((at(0x68000000)))),定义方式如下
         u32 testsram[250000] __attribute__((at(0x68000000)))



TFTLCD实验显示(三)-----FSMC
一直想总结一下这部分,但总感觉陌生,今天试着总结一下吧。

1.FSMC即灵活的静态存储控制器,能够与同步或异步存储器和16位PC存储器卡连接,其接口支持SRAM、NAND FLASH、NOR FLASH、PSRAM等存储器。

2.FSMC框图如下


3.上图中,FSMC将外部设备分为两种:其一,NOR/PSRAM设备;其二,NAND/PC卡设备。共享信号即他们共用的地址数据总线等信号。他们使用不同的CS来区分不同的设备。

4.FSMC框图信号含义(前缀N表示相关信号低电平有效)

     4.1.NOR FLASH,以非复用I/O为例,如下图


     4.2.PSRAM、SRAM,以非复用I/O为例,如下图


     4.3.NAND FLASH


     4.4.PC卡



5.为什么把TFTLCD当做SRAM设备用?


TFTLCD通过RS信号来决定传送的是数据还是命令,本质上可理解为一个地址信号,如接到A0上,那么当FSMC控制器写地址0的时候,A0为0,对TFTLCD来说就是写命令;而写地址1的时候,A0将会变成1,对TFTLCD来说就是写数据。这样,就把数据和命令区分开了。

6.FSMC存储块地址映像


如图,FSMC总共管理1GB(4Bank * (4*64M))。

7.FSMC存储块1,即Bank1。被分为4个区,每个区管理64M字节空间,都有独立的寄存器对所连接的存储块进行配置。
  HADDR是内部AHB地址总线,Bank1的256M字节空间由28根地址线(HADDR[27:0])寻址,其中HADDR[25:0]来自外部存储器地址FSMC_A[25:0],而HADDR[27:26]对四个区进行寻址。(-----FSMC_A[25:0]即与外部元器件连接的地址线)



8.需注意点:其一,不论外部接8位/16位宽设备,FSMC_A[0]永远接在外部设备地址A[0];其二,当使用16位数据宽度时,HADDR[0]并没有用到,对应关系变为HADDR[25:1]->FSMC[24:0],相当于右移一位;其三,HADDR[27:26]的设置是不需要我们干预的,选择某个区,即使用FSMC_NEx连接外部设备时,配置对应区寄存器组来适应外部设备即可。各存储块需配置寄存器如下


对于NOR FLASH控制器,主要通过FSMC_BCRx、FSMC_BTRx、FSMC_BWTRx寄存器设置(其中x=1~4,对应4个区)。通过这3个寄存器可以设置FSMC访问外部存储器的时序参数。

9.FSMC的NOR FLASH控制器支持同步和异步突发两种方式。
    9.1.同步突发访问方式,FSMC将HCLK分频后,发送给外部存储器作为同步时钟信号FSMC_CLK。此时需设置的时间参数有两个:其一,HCLK与FSMC_CLK的分频系数(CLKDIV),可2~16分频;其二,同步突发访问中获得第一个数据所需要的等待延时(DATLAT)。
    9.2.异步突发访问方式,FSMC主要设置三个时间参数,其一,地址建立时间(ADDSET);其二,数据建立时间(DATAST);其三,地址保持时间(ADDHLD)。FSMC综合SRAM/ROM、PSRAM、NOR FLASH信号特点,定义了四种不同异步时序模型,不同时序模型需设置不同的时序参数。

NOR FLASH支持的时序模型如图




10.MDK寄存器定义方式




11.实验中,TFTLCD的RS接在FSMC的A6上面,CS接在FSMC_NE4上面,并且是16位数据总线,即使用FSMC存储器1的第四区。定义了如下结构体


其中LCD_BASE必须根据外部电路的连接关系确定,使用Bank1.sector4就是从0X6C000000开始;而0X0000007E则是A6的偏移量,7E转换成二进制就是1111110,而16位数据时,地址右移一位对齐,即实际对应到地址引脚的时候就是A6:A0=0111111,此时A6是0,相当于RS=0,LCD->LCD_REG的地址就是0X6C00007E;如果16位地址加一(对应到8位地址是加2,即7E+0X02,结构体中元素都是u16类型,即16位),那么A6:10=1000000,此时A6是1,相当于RS=1,LCD->LCD_RAM的地址就是0X6C000080。

以上过程中,除A6位的值外,其他的各位取值状态对TFTLCD来说是没有任何意义的。0X6C000000是规定的选中区域的首地址,其余各位只是为了配合A6即RS的清零与置一而进行的赋值操作。


如上图,向FSMC某一地址(上述寄存器元素)送入数据,反应到LCD是两个过程:其一,FSMC控制地址A[18:0],对LCD来说只对RS即A6进行使用,判断是写入命令还是数据;其二,FSMC控制数据D[15:0],对LCD来说根据一中的RS判断数据类型,并相应写入。


相关/参考链接
【1】http://www.openedv.com/posts/list/54073.htm
【2】http://www.openedv.com/posts/list/44729.htm
【3】http://www.openedv.com/posts/list/33759.htm
【4】http://www.openedv.com/posts/list/47274.htm
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-30 22:59:21 | 显示全部楼层
回复【222楼】龙之谷:
---------------------------------
顶楼主
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-30 22:59:33 | 显示全部楼层
回复【223楼】龙之谷:
---------------------------------
这个比较详细了
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

5

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2015-8-21
在线时间
0 小时
发表于 2015-8-31 19:14:57 | 显示全部楼层
楼主加油,继续支持你。坚持就是胜利!
我是上次专门注册号顶你的围观群众。
我最近忙着毕设和找工作,压力很大,
不过每次看到楼主能在繁重的工作当中抽出时间来,坚持写这么大段的学习笔记,
就觉得自己的辛苦和压力也不算什么了。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-8-31 21:02:13 | 显示全部楼层
继续顶楼主..
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-8-31 23:34:24 | 显示全部楼层
第四一天  2015年08月31日  周一     例程:内存管理实验(一)



1.内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。主要目的是高效、快速的分配,并在适当的时候释放和回收内存资源。


2.分块式内存管理



分块式内存管理由两部分组成:其一,内存池;其二,内存管理表。内存池被等分为n项,对应的内存管理表也被等分为n项,内存管理表每一个项对应内存池的一块内存。当内存管理表为0时,代表对应的内存块未被使用,非0时代表该项对应的内存快已经被占用,其数值则代表被连续占用的内存块数。内存分配方向是从顶到底的分配方向。

3.分配原理与释放原理





数制转化
今天时间不怎么充足,整理了一些简单但却是一直想整理而没有静下心整理的小知识点。

十六进制与标准单位、十进制之间对应关系



十进制与十六进制对应关系



二进制与十进制、十六进制对应关系


以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-9-1 00:20:27 | 显示全部楼层
回复【228楼】龙之谷:
---------------------------------
不错。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-1 08:42:19 | 显示全部楼层
回复【226楼】neary:
---------------------------------
共同努力,共同进步

昨天晚上我哥回家路过石家庄,实在没时间,本打算在他到之前稍微整理一些一直想整理的小知识点就不再花费其他时间更新了,结果看到你的回复,还是临睡前,尽力整理一下,虽然东西不多,但到最后确实连回复你和原子老大的时间都没有了

毕设和找工作不要着急,时间充裕,当然早些找到理想的工作更好,祝顺利~
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-1 08:44:18 | 显示全部楼层
回复【229楼】正点原子:
---------------------------------
嘿嘿,谢老大~
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
27
金钱
27
注册时间
2015-7-5
在线时间
1 小时
发表于 2015-9-1 11:13:19 | 显示全部楼层
顶++  楼主真6
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-1 11:27:15 | 显示全部楼层
回复【232楼】影子白:
---------------------------------
嘿嘿,谢谢...
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-9-1 21:58:42 | 显示全部楼层
回复【230楼】龙之谷:
---------------------------------
支持啊。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-1 23:21:31 | 显示全部楼层
第四二天  2015年09月01日  周二     例程:内存管理实验(二)

1.本实验定义了三个内存池,如图


第一个和第三个都是内部内存,第一个是普通内存,地址从0X200000002开始,共128KB(主112KB+辅16KB);第三个是CCM内存,地址从0X10000000开始,共64KB,此部分仅CPU可访问,DMA等不可直接访问。
第二个是外部SRAM,地址从0X68000000开始,总共1024KB。

外部SRAM内存池指定地址为0X68000000,也就是从外部SRAM的首地址开始的;CCM内存池从0X10000000开始,同样是从CCM内存的首地址开始的;但是,内部SRAM内存池的首地址则由编译器自动分配。

2.__align(32)定义内存池首地址32字节对齐

3.内存泄漏,对一个指针进行多次内存申请,而之前申请的又没释放。

4.上一个实验:外部SRAM实验,我们定义了一个大数组u32 testsram【250000】 __attribute__((at(0x68000000))),编译后占用内存情况如下


当我们注释掉所有与大数组相关语句,编译后


也就是说大数组占用1000000字节ZI-data,正好是250000*(32/8)。

5.内存分块越小,内存管理表就越大,当分块为2字节1块的时候,内存管理表就和内存池一样大了(管理表每项都是u16类型)。

以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-1 23:37:35 | 显示全部楼层
上传个小截图,一直提示上传中,怕网速不好复制粘贴到word,各种无响应,我了个去去去去去去去,来回折腾浪费电时间没什么,这小心脏快炸了。。。

calm、calm、calm,继续发送测网速
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-2 00:17:26 | 显示全部楼层
2015年09月02日 00:22:38,就这么多吧,关于__attribute__冲突的问题解决方法与主观想法不一致,再想想...
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-2 23:16:06 | 显示全部楼层
第四三天  2015年09月02日  周二     例程:内存管理实验(三)



一.先把昨天没有想明白的问题解决掉:做关于内存管理实验较为容易碰到的报错如下


大致就是定义变量(地址)地址重叠/冲突,主要是与地址有关,如果做实验的小伙伴从上一个SRAM实验通过添加程序进行内存管理实验忘了删除原来定义的u32 testsram【250000】就会进行上述类似报错,那么如果多次指定不同数组起始地址,什么情况会报错及如何解决呢?

为了测试这个问题,我们可以定义三个数组,均是32位数据类型25个数组元素,即每个数组占25*4=100字节


     第一种情况:(如下)三个数组同一指定起始地址,是否正确?正确!
三个数组就像同一级别的数组定义顺序排布
[mw_shl_code=c,true]u32 testsram1[25] __attribute__((at(0x68000000))); //①所测起始地址0X68000000 u32 testsram2[25] __attribute__((at(0x68000000))); //②所测起始地址0X68000064 u32 testsram3[25] __attribute__((at(0x68000000))); //③所测起始地址0X680000C8[/mw_shl_code]
   
    第二种情况:(如下)三个数组两个同一起始地址,一个起始地址后移100自己,即一个数组占用空间,是否正确?错误!
这也就是我们从SRAM实验到内存管理实验没有删除testsram数组造成报错的情况,为什么此时会报错?如何解决?我们继续看其他情况,然后从中找出问题所在...
[mw_shl_code=c,true]u32 testsram1[25] __attribute__((at(0x68000000))); u32 testsram2[25] __attribute__((at(0x68000000+25*4))); u32 testsram3[25] __attribute__((at(0x68000000)));[/mw_shl_code]
     
    第三种情况:(如下)在第二种情况基础上,进一步右移,使其右移200字节,也就是定义的两个数组所占空间,是否正确?正确!
与第二种情况对比,我们可以发现,貌似每个__attribute__就像是在它指定的地址划了一条“三八”线,这条线不可随意跨越,在线之前用指定地址存放的数据必须在线之前存储完毕,同一指定起始地址就视为同等级别,依次放置,如果在两条"三八"线之间数据没有存放完整只有一个结果-----报错。
[mw_shl_code=c,true]u32 testsram1[25] __attribute__((at(0x68000000))); //①所测起始地址0X68000000 u32 testsram2[25] __attribute__((at(0x68000000+25*4*2))); //②所测起始地址0X680000C8 u32 testsram3[25] __attribute__((at(0x68000000))); //③所测起始地址0X68000064[/mw_shl_code]
另:以上三个数组是并列关系,谁在前谁在后只是各自对应地址会有变化,不存在先后顺序关系,即如上图,假如①和③调换位置,各自对应地址也会交换,而②无论在什么位置地址都是固定的,因为它的指定地址与另外两个不同,是固定的。

     第四种情况:(如下)同一数组两个指定起始地址,是否正确?正确!
这种情况此数组的起始地址以第二次指定地址为准,即如果下图中①与③位置对换,则testsram1起始地址为0X68000000,而如下图情况时testsram1的起始地址为0X68000064。
[mw_shl_code=c,true]u32 testsram1[25] __attribute__((at(0x68000000))); //① u32 testsram2[25] __attribute__((at(0x68000000))); //②所测起始地址0X68000000 u32 testsram1[25] __attribute__((at(0x68000000+25*4))); //③所测起始地址0X68000064[/mw_shl_code]

总结:1.对同一块区域使用attribute,我们可以直接指定多个数据同一起始地址,程序会自动依次存放,既简单又省事。
2.如果要指定不同起始地址,确保每次前一次attribute所指定地址到第二次attribute指定地址之间的变量有足够空间存放,才能第二次使用attribute指定地址。
3.对于attribute不熟悉,网上资料没看明白,深究意义也不是很大,故在此仅作以上测试层面简单分析。

二、内存管理实验中,是如何在三个内存空间实现切换的?

1.首先定义一个结构体来统一管理程序常用函数/变量
[mw_shl_code=c,true]//内存管理控制器 struct _m_mallco_dev { void (*init)(u8); //初始化 u8 (*perused)(u8); //内存使用率 u8 *membase[SRAMBANK]; //内存池 管理SRAMBANK个区域的内存 u16 *memmap[SRAMBANK]; //内存管理状态表 u8 memrdy[SRAMBANK]; //内存管理是否就绪 }; extern struct _m_mallco_dev mallco_dev; //在mallco.c里面定义[/mw_shl_code]

2.定义完以后初始化是必须的

[mw_shl_code=c,true]//内存管理控制器 struct _m_mallco_dev mallco_dev= { my_mem_init, //内存初始化 my_mem_perused, //内存使用率 mem1base,mem2base,mem3base, //内存池 mem1mapbase,mem2mapbase,mem3mapbase,//内存管理状态表 0,0,0, //内存管理未就绪 };[/mw_shl_code]

3.初始化中前两行是两个函数元素,前面已经简单分析过,我们主要看第三四行的数组赋值
。第三四行赋值来源如下
[mw_shl_code=c,true]//内存池(32字节对齐) __align(32) u8 mem1base[MEM1_MAX_SIZE]; //内部SRAM内存池 __align(32) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000))); //外部SRAM内存池 __align(32) u8 mem3base[MEM3_MAX_SIZE] __attribute__((at(0X10000000))); //内部CCM内存池 //内存管理表 u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; //内部SRAM内存池MAP u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X68000000+MEM2_MAX_SIZE))); //外部SRAM内存池MAP u16 mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((at(0X10000000+MEM3_MAX_SIZE))); //内部CCM内存池MAP[/mw_shl_code]
也就是将内存池/内存管理表的数组指针(地址)赋值给返回值为指针的(内存池/内存管理表)数组。

4.
通过数组下标来进行不同区域内存管理。
[mw_shl_code=c,true]//内存管理初始化   //memx:所属内存块 void my_mem_init(u8 memx)   {       mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);//内存状态表数据清零   mymemset(mallco_dev.membase[memx], 0,memsize[memx]); //内存池所有数据清零   mallco_dev.memrdy[memx]=1; //内存管理初始化OK   }   [/mw_shl_code]
其中,mymemset函数如下
[mw_shl_code=c,true]//设置内存 //*s:内存首地址 //c :要设置的值 //count:需要设置的内存大小(字节为单位) void mymemset(void *s,u8 c,u32 count) { u8 *xs = s; while(count--)*xs++=c; } [/mw_shl_code]

三、开发指南中,内存管理实验实际是定义了一个大的数组,内存分配与释放是对这个大的数组进行的部分元素的使用与释放,这个数组是放在静态存储区的而非堆区,只有使用了系统malloc函数申请的空间才会放在堆区中(具体请看相关/参考链接【1】中各楼层讨论介绍
)。

内存组成分为一下几部分:【注,如与其他资料描述相悖,请不要以此为准】

1.静态存储区(全局区static),全局变量和静态变量存储区域,初始化的全局变量和静态变量存放在一块区域,而为初始化的全局变量和静态变量存放在相邻另一区域,未初始化的程序结束后由系统释放。
2.堆区(heap),一般由程序员分配释放,分配方式类似于链表。
3.栈区(stack),编译器自动分配释放,存放函数参数值、局部变量值等。
4.文字常量区,常量字符串存放区域,const之类常量,是存放在flash中的。
5.程序代码区,存放函数体的二进制代码。

网络大家比较推荐的一个前辈程序
[mw_shl_code=c,true] //main.cpp int a = 0; //全局初始化区 char *p1; //全局未初始化区 main() { int b; //栈 char s[] = "abc"; //栈 char *p2; //栈 char *p3 = "123456"; //123456\0在常量区,p3在栈上。 static int c =0; //全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); // 分配得来得10和20字节的区域就在堆区。 strcpy(p1, "123456"); // 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 } [/mw_shl_code]



【结合STM32F1中文参考手册(较为熟悉,容易找到所需框图)与STM32F4中文参考手册进行总结】





上图截自stm32f103参考手册,可与CM3权威指南框图进行对照学习,如下




此时,可对存储区域稍作整理




参考/相关链接:
【1】http://www.openedv.com/posts/list/0/24152.htm(此帖及各楼层讨论非常值得反复学习思考)
【2】http://blog.chinaunix.net/uid-11959329-id-2797040.html
【3】http://www.openedv.com/posts/list/28280.htm
【4】http://www.cnblogs.com/hanyonglu/archive/2011/04/12/2014212.html
【5】http://wenku.baidu.com/link?url=UKhX5hsDqEJ-CFWexV64Qo6WK_IrcAwGe6TrMpdE6S1WOMLptQY5lovTi1e0peGUdB5Og5hMlmAT0MBzkRwwsqYHXGTzboYmfGrk_ZUaEdS
【6】http://blog.csdn.net/slj_win/article/details/16906141
【7】http://www.openedv.com/posts/list/39809.htm
【8】http://www.openedv.com/posts/list/23456.htm
【9】http://www.openedv.com/posts/list/58590.htm
【10】http://www.openedv.com/posts/list/45339.htm
【11】http://blog.163.com/xuanmingzhiyou@yeah/blog/static/14247767620122111272980/
【12】http://blog.csdn.net/l_chxu/article/details/8841668
【13】http://www.cnblogs.com/hanyonglu/archive/2011/04/28/2031271.html
【14】http://www.cnblogs.com/longyi1234/archive/2010/03/22/malloc.html
【15】http://www.jb51.net/article/36391.htm
【16】http://www.openedv.com/posts/list/26805.htm
【17】http://www.openedv.com/posts/list/26602.htm

以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-2 23:42:02 | 显示全部楼层
关于放假器件9月3号~9月5号更新情况:
3号、4号回家,家中没有网络,不会进行实时更新,但在家中可能会进行整理,如果整理满足两个条件就会在5号回来后进行补充更新。两个条件:其一,先保证时间,整理时间需超过两个小时;其二,保证完成时限,需在凌晨一点前完成有效。

本不打算回家了,但由于老哥工作原因,我们哥俩经常交错回家,已有两年时间没有一家人团聚了,此次正好老哥回家我也放假,一家人能有短暂团聚。

很多人都有一种想法,等我怎么着怎么着好好孝敬父母,我也如此,但感觉现在工作进展还是太慢,父母也渐渐老了,尽自己所能吧,父母也不图什么,仔细香香,我们现在的不作为,等事业有成只不过是现在的懒惰而已,现在就开始孝敬父母不会影响以后孝敬父母更不会影响事业成功与否,然而,等事业可能有成以后再孝敬父母则直接损失了很多可以孝敬父母的时间。

有感而发,不吐不快,呵呵,祝各位快乐顺利~~~~~
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-2 23:47:34 | 显示全部楼层
回复【226楼】neary:
---------------------------------
当你感到忙碌的时候也是你进步最大的时候

假期快乐,祝顺利
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-2 23:49:49 | 显示全部楼层
祝原子老大假期快乐,感谢老大的鼓励...
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-5 23:19:12 | 显示全部楼层
2015年9月3号、4号、5号  无更新

抗日70周年阅兵,全国放假,回家三天,期间虽有小整理,但多为图片截图,几无文字串联,杂七散八,权做日后些许素材
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-9-5 23:26:27 | 显示全部楼层
回复【242楼】龙之谷:
---------------------------------
明天有更新了,呵呵
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

28

主题

187

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
381
金钱
381
注册时间
2014-10-9
在线时间
6 小时
发表于 2015-9-6 13:28:59 | 显示全部楼层
非常喜欢,支持楼主!!
拿什么让你自己信服 自己
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-6 21:03:47 | 显示全部楼层
回复【244楼】真的好多巧合:
---------------------------------
my pleasure

共同进步~
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-6 23:21:56 | 显示全部楼层
第四四天  2015年09月06日  周日     例程:SD卡实验(一)

1.SD卡,支持SPI/SDIO驱动。使用STM32F4自带的SDIO接口驱动,4位模式,最高通信速度可达48MHz,最高每秒可传输数据24M字节。所有数据线都工作在推挽模式。

2.SDIO的3个时钟


时钟分频器不旁路时SDIO_CK = SDIOCLK/(2+CLKDIV);其中,SDIOCLK一般是48MHz,CLKDIV是分频系数,通过SDIO_CLKCR配置;
时钟分频器旁路时,SDIO_CK = SDIOCLK。

3.SD卡初始化的时候,时钟频率SDIO_CK不能超过400KHz,否则无法完成初始化,完成初始化以后,可以在SD卡最大操作时钟频率范围进行设置。


4.将卡分为4类:其一,SD2.0高容量卡,SDHC最大32G;

其二,SD2.0标准容量卡,SDSC最大2G;
其三,SD1.x卡;
其四,MMC卡。

5.操作SDIO_FIFO(读出/写入)必须是以4字节对齐的内存进行操作,否则将导致出错。在调用操作SDIO_FIFO函数时,提供给函数的参数数据缓存区不一定式4字节对齐的,故定义一个4字节对齐缓存,
[mw_shl_code=c,true]//SD_ReadDisk/SD_WriteDisk函数专用buf,当这两个函数的数据缓存区地址不是4字节对齐的时候, //需要用到该数组,确保数据缓存区地址是4字节对齐的. __align(4) u8 SDIO_DATA_BUFFER[512]; [/mw_shl_code]
当非4字节对齐时,将数据复制存放到此数组进行过渡处理,以确保传递给底层读写函数的参数是4字节对齐的。
[mw_shl_code=c,true]memcpy(SDIO_DATA_BUFFER,buf,512); //单个扇区数据复制[/mw_shl_code]

6.轮询方式,读写FIFO时,严禁任何中断打断,否则可能导致数据出错,所以使用INTX_DISABLE函数关闭总中断,在FIFO读写结束后才通过INTX_ENABLE打开总中断,这两个函数在sys.c文件中实现,实现如下
[mw_shl_code=c,true]//关闭所有中断(但是不包括fault和NMI中断) __asm void INTX_DISABLE(void) { CPSID I BX LR } //开启所有中断 __asm void INTX_ENABLE(void) { CPSIE I BX LR }[/mw_shl_code]

以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-6 23:47:29 | 显示全部楼层
刚开帖的时候也是打算记录一下心路历程,以自己为例做个实验,看个人的耐心及坚持中会有什么感受,由于前期的浮躁没有静下心来写,现在准备大概写一些,当然可能有正面的也可能会有负面的,请绕行。

先对以前四十四天进行简单回顾:
第一阶段:前七八天左右,开始新的规律的学习方式,新奇且充满动力,当然,由于是新事物没有形成一定习惯,所以也会有一些阻力,但最终动力获胜。
第二阶段:第一阶段后,动力逐渐减弱,到前三十天,每隔十几天会有一次比较大的惰性来袭,非常想玩游戏或看电影等,当天不想继续更新。
第三阶段:第二阶段后,到前四十天,习惯基本养成,但动力不大惰性也不大,基本有些麻木的感觉,更新不需要克服什么也没有什么热情。
第四阶段:暂以四十天到现在第四十四天为例吧,放假回家仍然想继续更新,应该是进一步习惯了;但家里毕竟没有网络等条件,断更三天,回来后,要继续更新有一些动力,同时也想着玩游戏等,可见习惯的建立还是不够稳固的,人还是趋于安逸的一种情绪。

当然,对更新知识的掌握程度,更新内容的整理难易会直接影响到更新的动力与逃避的惰性,不再深入思索。
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-9-7 00:24:25 | 显示全部楼层
回复【247楼】龙之谷:
---------------------------------
坚持就是胜利,我都想早上起来跑步的。。。
可惜总是起不来啊。。。找不回以前的动力了。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-7 23:06:26 | 显示全部楼层
第四五天  2015年09月07日  周一     例程:SD卡实验(二)

SD卡相关函数及内容之多远超我能力范围,故在此只对少数函数进行一些分析学习。
1.SDIO时钟初始化设置
[mw_shl_code=c,true]/********************************************************************* 功能 :SDIO时钟初始化设置 //clkdiv:时钟分频系数 //CK时钟=SDIOCLK/[clkdiv+2];(SDIOCLK时钟固定为48Mhz) ********************************************************************************************/ void SDIO_Clock_Set(u8 clkdiv) { u32 tmpreg=SDIO->CLKCR; tmpreg&=0XFFFFFF00; tmpreg|=clkdiv; SDIO->CLKCR=tmpreg; }[/mw_shl_code]
过程:读取SDIO->CLKCR寄存器原值,配置相应位,写入寄存器。阅读开发指南程序感觉极简单,但如果需要自己去写,是否能够通过阅读手册轻松配置出来呢?单片机很多需要处理的工作就是对寄存器的配置,配置过程也是如上流程,我们需要多看几遍以上流程,对此过程了熟于心,则学习之路会轻松许多。配置寄存器既简单又复杂,简单就是基本直接按照手册对寄存器进行写入即可,复杂在于我们在没有参考书或例程的时候不敢轻易去写,或者说没有信心去写。

2.响应的错误状态
[mw_shl_code=c,true]/********************************************************************* 功能 :检查R2响应的错误状态 //返回值:错误状态 ********************************************************************************************/ SD_Error CmdResp2Error(void) { SD_Error errorstatus=SD_OK; u32 status; u32 timeout=SDIO_CMD0TIMEOUT; while(timeout--) { status=SDIO->STA; if(status&((1<<0)|(1<<2)|(1<<6)))break;//CRC错误/命令响应超时/已经收到响应(CRC校验成功) } if((timeout==0)||(status&(1<<2))) //响应超时 { errorstatus=SD_CMD_RSP_TIMEOUT; SDIO->ICR|=1<<2; //清除命令响应超时标志 return errorstatus; } if(status&1<<0) //CRC错误 { errorstatus=SD_CMD_CRC_FAIL; SDIO->ICR|=1<<0; //清除响应标志 } SDIO->ICR=0X5FF; //清除标记 return errorstatus; } [/mw_shl_code]
对错误响应状态的甄别,先对相应(错误/正确)位进行检查,根据相应位的状态判断响应状态,并通过不同值的返回体现出来。

3.发送命令函数
[mw_shl_code=c,true]/********************************************************************* 功能 :SDIO发送命令函数 //cmdindex:命令索引,低六位有效 //waitrsp:期待的相应.00/10,无响应;01,短响应;11,长响应 //arg:参数 ********************************************************************************************/ void SDIO_Send_Cmd(u8 cmdindex,u8 waitrsp,u32 arg) { u32 tmpreg; SDIO->ARG=arg; tmpreg=SDIO->CMD; tmpreg&=0XFFFFF800; //清除index和waitrsp tmpreg|=cmdindex&0X3F; //设置新的index tmpreg|=waitrsp<<6; //设置新的wait rsp tmpreg|=0<<8; //无等待 tmpreg|=1<<10; //命令通道状态机使能 SDIO->CMD=tmpreg; }[/mw_shl_code]
是对两个寄存器ARG、CMD进行了配置操作,把常用/全部命令进行宏定义,对需要到的配置直接进行宏定义替换,使程序读写更加人性化与规范化。如命令集宏定义如下
[mw_shl_code=c,true]//SDIO 指令集 #define SD_CMD_GO_IDLE_STATE ((u8)0) #define SD_CMD_SEND_OP_COND ((u8)1) #define SD_CMD_ALL_SEND_CID ((u8)2) #define SD_CMD_SET_REL_ADDR ((u8)3) /*!< SDIO_SEND_REL_ADDR for SD Card */ #define SD_CMD_SET_DSR ((u8)4) #define SD_CMD_SDIO_SEN_OP_COND ((u8)5) #define SD_CMD_HS_SWITCH ((u8)6) #define SD_CMD_SEL_DESEL_CARD ((u8)7) #define SD_CMD_HS_SEND_EXT_CSD ((u8)8) #define SD_CMD_SEND_CSD ((u8)9) #define SD_CMD_SEND_CID ((u8)10) #define SD_CMD_READ_DAT_UNTIL_STOP ((u8)11) /*!< SD Card doesn't support it */ #define SD_CMD_STOP_TRANSMISSION ((u8)12) #define SD_CMD_SEND_STATUS ((u8)13) #define SD_CMD_HS_BUSTEST_READ ((u8)14) #define SD_CMD_GO_INACTIVE_STATE ((u8)15) #define SD_CMD_SET_BLOCKLEN ((u8)16) #define SD_CMD_READ_SINGLE_BLOCK ((u8)17) #define SD_CMD_READ_MULT_BLOCK ((u8)18) #define SD_CMD_HS_BUSTEST_WRITE ((u8)19) #define SD_CMD_WRITE_DAT_UNTIL_STOP ((u8)20) #define SD_CMD_SET_BLOCK_COUNT ((u8)23) #define SD_CMD_WRITE_SINGLE_BLOCK ((u8)24) #define SD_CMD_WRITE_MULT_BLOCK ((u8)25) #define SD_CMD_PROG_CID ((u8)26) #define SD_CMD_PROG_CSD ((u8)27) ......[/mw_shl_code]

对应ARG、CMD寄存器描述如下













相关/参考链接
【1】http://www.openedv.com/posts/list/13815.htm
【2】http://www.openedv.com/posts/list/6430.htm
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
 楼主| 发表于 2015-9-7 23:08:04 | 显示全部楼层
回复【248楼】正点原子:
---------------------------------
哈哈,还是要抽时间锻炼锻炼

正想着更新完这篇开个跑步记录帖,督促自己坚持跑步...
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-22 11:53

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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