最新日志

发表于:2008-7-28 21:43:54
标签:STM32——SD  

2

万利板子上创建SD卡的FAT文件系统(一)

万利的板子上创建SD卡文件系统 (一)

                       ---SD卡读写

    之前在AVR上做过SDFAT文件系统,万利的EK-STM32F板子上有SD接口,正好可以做一个基于SDFAT文件系统,打算要做成支持FAT32FAT16,通过串口与PC连接,可以显示SD卡中的文件信息,也可以把文件读出来,例如,把指定文件名的txt文件通过串口显示到PC

 这是Keil3。22下的工程 点击下载

  

   我是去年过年以前决定开始做MP3,由于一直用AVR,所以自然就选用那个流传最广的方案——AVRSDVS1003,自己做了PCB,最后终于做成了,主要参考www.ourdev.cn上波仔的MEGA8版本的MP3(感谢波仔),其间花了大量时间学习SD卡读写和FAT文件系统的知识,现在正好用上。

   昨天晚上本来想用KEILSD卡工程,但是一直不成功,于是转到以前在AVR上的代码上来最后终于读出0扇区,而且与读卡器加WinHEX软件读出来的一致(有图为证)。我用的是Keil3.22,这个版本比较新,可以从Keil的中文网站上下载,最大的好处就是使用方便,已经开始支持JLink2了,万利的板子可以用Keil调试了,当然老版本的Keil可以先生成hex再用串口烧写到STM32

EKSTM32F板子上使用的是SPI1访问SD卡,还有一个SD卡的PowerCS线,另外一个PA2接到了SD卡插入检测,大家可以不理会,(万利不专业,原理图上没有画出来,板子背面写了)。

 

软件:Keil3.22建立的工程

 

硬件:

  SD     STM32

 SCK     PA5

 MISO    PA6

 MOSI    PA7

 POWER  PD10

  CS     PD9

具体的可以参考原理图,这个光盘里有,万利网站上有。

SPIGPIO的初始化如下。

void SPI_Config(void)

{

  GPIO_InitTypeDef  GPIO_InitStructure;

  SPI_InitTypeDef   SPI_InitStructure;

 

  /* GPIOA and GPIOD Periph clock enable */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);

  /* SPI1 Periph clock enable */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

 

  /* Configure SPI1 pins: SCK, MISO and MOSI */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

 

  /* Configure PD9 pin: CS pin  ,PD10 : SD Power*/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

 

  /* SPI1 Config */

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

  SPI_InitStructure.SPI_CRCPolynomial = 7;

  SPI_Init(SPI1, &SPI_InitStructure);

 

  /* SPI1 enable */

  SPI_Cmd(SPI1, ENABLE);

}

 

定义两个宏,分别是SD卡选中和不选中

#define   SPI_CS_Assert()     GPIO_ResetBits(GPIOD, GPIO_Pin_9)

/* Deselect MSD Card: ChipSelect pin high */

#define SPI_CS_Deassert()    GPIO_SetBits(GPIOD, GPIO_Pin_9)

 

对于万利的板子,还要一个上电的过程,该MOS管是的电平导通。

SPI初始化之后,我加了一句GPIO_ResetBits(GPIOD, GPIO_Pin_10);就是SD上电。注意上电之后,最好有一段延时,这样给SD内部初始化流充足的时间,避免初始化的失败。

初始化SD卡代码如下:

//sd卡复位          //reset sd card (software)

uint8 MMC_SD_Reset(void)

{

       uint8 i;

       uint8 retry;

       uint8 r1=0;

       retry = 0;

 

       SPI_Config();

    GPIO_ResetBits(GPIOD, GPIO_Pin_10);  // SD卡上电,打开MOS

    delay(1000);                         // 重要的延时

  /* MSD chip select high */

    SPI_CS_Deassert();

       do

       {

              for(i=0;i<10;i++) SPI_WriteByte(0xff);

              r1 = MMC_SD_SendCommand(0, 0);//idle命令    //send idle command

              retry++;

              if(retry>100) return 1;//超时退出            //time out

       } while(r1 != 0x01);   

 

 

       retry = 0;

       do

       {

              r1 = MMC_SD_SendCommand(1, 0);//active命令       //send active command

              retry++;

              if(retry>200) return 1;//超时退出            //time out

       } while(r1);

       //SPI_High();

       r1 = MMC_SD_SendCommand(59, 0);//crc           //disable CRC

 

       r1 = MMC_SD_SendCommand(16, 512);//设扇区大小512    //set sector size to 512

       return 0;//正常返回           //normal return

}

 

还有两个基本函数,即写和读SPI(读写合二为一)

unsigned char SPI_WriteByte(unsigned char data)

{

 uint8 Data = 0;

 

  /* Wait until the transmit buffer is empty */

  while (SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET);

  /* Send the byte */

  SPI_SendData(SPI1, data);

 

  /* Wait until a data is received */

  while (SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == RESET);

  /* Get the received data */

  Data = SPI_ReceiveData(SPI1);

 

  /* Return the shifted data */

  return Data;

}

 

SD卡中写一个命令的函数

 

//sd卡写命令             //sd send command

uint8 MMC_SD_SendCommand(uint8 cmd, uint32 arg)

{

       uint8 r1;

       uint8 retry="0";

      

       SPI_WriteByte(0xff);

       SPI_CS_Assert();

      

       SPI_WriteByte(cmd | 0x40);//分别写入命令 //send command

       SPI_WriteByte(arg>>24);

       SPI_WriteByte(arg>>16);

       SPI_WriteByte(arg>>8);

       SPI_WriteByte(arg);

       SPI_WriteByte(0x95);

      

       while((r1 = SPI_WriteByte(0xff)) == 0xff)//等待响应,     //wait response

              if(retry++ > 200) break;//超时退出                             //time out error

 

       SPI_CS_Deassert();

 

       return r1;//返回状态值                                  //return state

}

 

有了这些函数之后就可以读写SD卡了,主要是读一个扇区及写一个扇区,注意SD卡只能是读写扇区,即512 个字节。具体代码见我的工程文件的SD_MMC.c uint8 MMC_SD_ReadSingleBlock(uint32 sector, uint8* buffer)  读第sector扇区到Bufferuint8 MMC_SD_WriteSingleBlock(uint32 sector, uint8* buffer)是写扇区。

{

 

为了调试方便,我把串口1接上了(最左边哪个口),初始化成功后,把0扇区的512个字节读出来,大部分为0,只有前后的一些字节不为0,调试助手接到的字符为

3|P P­ <t<uuL[1]t<t<tV ^|[1]W_s3Ou}=Uu|Invalid partition tableError loading operating systemMissing operating system

在串口助手和Winhex软件读出来的分别是下图:

点击开大图 

点击开大图

每个人的电脑和SD卡不同,这些数据会有小差异,但基本相同,如果你的试验也是这些数据,那么,恭喜你,你也做成SD卡读写试验了,没成功也不要紧,检查SD卡插紧了没有。跳线接了没有,量量电压对不对,等等,一定能做成。

还有很多人用IAR,可以把我的几个文件拷到你的IAR工程,编译,调试,不难的,我开始也用的IAR

 

   好了,第一课就上到这里,下一次开始介绍FAT了,谢谢你的关注,如果你参考我的例子做成了,或者认为我的代码和经验有帮助,就顶我一下啊。祝你好运。

点击此处查看原文 >>

系统分类: 单片机   |    用户分类:    |    来源: 原创

评论(0) | 阅读(297)
发表于:2008-5-10 15:03:24
标签:STM32  USB  KEIL  

0

STM32 的 USB_MOUSE例子详解及改造(用KEIL MDK在EK-STM32)

这个例子是用EK的板子上的KEY4实现一个鼠标,不需要自己编USB驱动,因为使用标准的HID

用KEIL打开那个USB例子的工程,在main.c:
 while (1)
  {
    Delay(10000);
    if (JoyState() != 0)
    {
      Joystick_Send(JoyState());
    }
  }
可以看到 主程序不断循环检测按键,一旦有键按下,就通过USB发送到PC.
这里说明一下,鼠标发送的有用数据是4个字节,0字节的bit0表示鼠标左键单击,bit1是右键
  1字节是X位置,2字节是Y位置,3号字节我没弄清除
然后打开hw_config.h和hw_config.c这两个是硬件配置,主要是按键

.
检测.
在.h开始加上
#define DOWN            1
#define LEFT            2
#define RIGHT           3
#define UP              4
#define SEL    7
#define CURSOR_STEP     5   //原来的版本是30 ,被我改成5 这样每次移动时鼠标更准确
#define LEFT_CLICK       8  //这两个是我加的 ,把板子上的KEY2和KEY3作为左键和右键
#define RIGHT_CLICK      9
相应的.c文件也有改动
u8 JoyState(void)
{
  ......前面4个按键检测我这里省略不写了,我没有改动,下面是我添的
  if (!GPIO_ReadInputDataBit(GPIOD, JOY_SEL))
  {
    return SEL;
  }
  if (!GPIO_ReadInputDataBit(GPIOD, MISE_LEFT))
  {
    return LEFT_CLICK;
  }
  if (!GPIO_ReadInputDataBit(GPIOD, MISE_RIGHT))
  {
    return  RIGHT_CLICK;
  }

  /* No key is pressed */
  else
  {
    return 0;
  }
}
在USB发送函数,我也添加了几条如下:
void Joystick_Send(u8 Keys)
{
  u8 Mouse_Buffer[4] = {0, 0, 0, 0};
  s8 X = 0, Y = 0;
  //u8 Sel_flag=0;
  switch (Keys)
  {
    case LEFT:
      X -= CURSOR_STEP;  //左键按下, 以下类似
      break;
    case RIGHT:

      X += CURSOR_STEP;
      break;
    case UP:
      Y -= CURSOR_STEP;
      break;
    case DOWN:
      Y += CURSOR_STEP;
    case  SEL:
 //  Sel_flag=1;
   break;
//鼠标发送的有用数据是4个字节,0字节的bit0表示鼠标左键单击,bit1是右键
    case  LEFT_CLICK:
   Mouse_Buffer[0] =0x01; //上面说了,鼠标发送的4个字节的0号字节有左右键信息.
      break;
    case  RIGHT_CLICK:
      Mouse_Buffer[0]=0x02;
      break;
    default:
      return;
  }

  /* prepare buffer to send */
  Mouse_Buffer[1] = X;
  Mouse_Buffer[2] = Y;
 
  /*copy mouse position info in ENDP1 Tx Packet Memory Area*/
  UserToPMABufferCopy(Mouse_Buffer, GetEPTxAddr(ENDP1), 4);
  /* enable endpoint for transmission */
  SetEPTxValid(ENDP1);
}

上面先根据按键的信息确定XY坐标,任何左右键信息然后调用:
UserToPMABufferCopy(Mouse_Buffer, GetEPTxAddr(ENDP1), 4);把4个字节
通过USB发送出去,UserToPMABufferCopy()是USB库的底层驱动
好了,程序写完了,我们先保存再F7一下生成HEX.再把板子的BOOT0跳线设为1,BOOT1为0
然后用ST的串口ISP软件烧进STM32去.断电后再把BOOT0设为0.
USB插到板子右边那个USB口,USBEN跳线接到0.过几秒钟,左右按动KEY4,电脑上的鼠标点击标志
是不是移动了,如果是,恭喜你,你成功了,要没动的话,可以断电后再试一次.(检查跳线,USBEN应为0)
工程的说明文档Readme.TXT建议说最好先运行STM32 再插USB线,你可以通过2根USB线来实现,
先插上板子左边那个USB,供电跳线选STLINK2,过一段实践后插右边的USB口,这样被PC识别率会高.


在IAR的例子上,其实是一样的,IAR例子用SELEC来实现单击,有EK板子的可以试试.这个例子对于学USB

比较简单.

点击此处查看原文 >>

系统分类: ARM   |    用户分类:    |    来源: 原创

评论(0) | 阅读(360)
发表于:2008-5-10 14:49:42
标签:用KEIL开发STM32  

0

EKSTM32+Keil MDK +串口ISP来学习STM32

EKSTM32的板子一般是用IAR来编译调试的,因为板上集成的STLINK2被IAR支持,但是我个人认为IAR的工程管理不太好,各种源文件,头文件在Wokeplace的位置让初学者摸不着头脑,还不如用KEIL,环境跟以前单片机的差不多.缺点是不能用STLINK2的USB调试了,但是我们可以回到单片机的ISP方式下来烧写.
以后自己做STM32 的板子,没钱的话也买不起独立的STLINK2,还是从串口IAP实惠,不要钱

需要的硬件是EK-STM32F,软件用KEIL的Uvision3 从KEIL的中文网站上下载,还有几个EK-STM32例子,

可以一并下载.烧写软件用ST的官方烧写FLSH软件 STMicroelectronics flash loader.exe,600K大

小,可以从ST中文网站或者万利的网站下载.

 

以KEIL的UART-DEMO为例:
首先打开KEIL,project--open project打开uvision3格式的UART的DEMO工程,选择project下的

building或者按F7键就可以编译,生成的HEX文件在工程保存目录的output文件夹.
板子先把BOOT0跳线接1, BOOT1接0,(BOOT选择是在液晶的左边)这样STM32 芯片就可以从内部一个特

殊的FLASH启动,所谓的SSTEM FLASH,专门用来从串口1接受PC的数据,然后写到STM32 用户FLASH.


板子上电  ,打开 STMicroelectronics flash loader,点击NEXT,(串口不用设置,默认设置,STM32会自自动识别波特率)选择Download,并打开刚才生成的HEX 文件(这个FLASHLOADER默认打开BIN,在选择HEX文件时要把打开文件的格式选为HEX才能看见HEX文件),再点击NEXT,很快就烧完了.
烧完后断电,把BOOT0改成1,上电后就可以从用户FLASH启动,这里面的内容就是刚才烧进去的.
如果没有问题,运行这个例子的结果是  液晶上显示PASS.
祝大家好运,我懒得传设置的图片了.

工程在这:点击下载

点击此处查看原文 >>

系统分类: ARM   |    用户分类:    |    来源: 原创

评论(0) | 阅读(346)
发表于:2008-4-28 22:01:52
标签:OrCAD  教程  

2

OrCAD入门教程

这是一个PDF的OrCAD入门教程,希望对初学者有帮助点击下载

觉得好的吆喝一声,哈哈

点击此处查看原文 >>

系统分类: PCB   |    用户分类:    |    来源: 整理

评论(1) | 阅读(541)
发表于:2008-4-28 21:51:58
标签:STM32  与Cortex-M3  ARM  

0

STM32介绍以及与通常ARM的区别

ARM是英国的芯片设计公司,其最成功的莫过于32位嵌入式CPU核----ARM系列,最常用的是ARM7和ARM9,

ARM公司主要提供IP核,就是CPU的内核结构,只包括最核心的部分,并不是完整的处理器. ARM把这个核卖给各大半导体公司,如 Pllips 三星 ,ATMEL 等等,许多公司,甚至Intel.

ARM为了对付 8位机市场,最近推出了 Cortex-M3核,STM32就是意大利的意法半导体基于Cortex-M3的32位嵌入式处理器, Cortex_M3核 性价比更高,价格低,可以与8位单片机竞争.

STM32 性能如下:

功能
■ 核心
- ARM 32位的Cortex(TM)-M3CPU
- 72MHz,高达90DMips,1.25DMips/MHz
-  单周期硬件乘法和除法——加快计算
■  存储器
-  从32K字节至128K字节闪存程序存储器
-  从6K字节至20K字节SRAM
-  多重自举功能
■  时钟、复位和供电管理
- 2.0至3.6伏供电和I/O管脚
 
-  上电/断电复位(POR/PDR)、可编程电压监
■  多达7个定时器
测器(PVD)、掉电监测器
-  多达3个同步的16位定时器,每个定时器有
-  内嵌4至16MHz高速晶体振荡器
多达4个用于输入捕获/输出比较/PWM或脉
-  内嵌经出厂调校的8MHz的RC振荡器
冲计数的通道
-  内嵌40kHz的RC振荡器
- 16位6通道高级控制定时器
-  内嵌PLL供应CPU时钟
- 多达6路PWM输出
-  内嵌使用外部32kHz晶体的RTC振荡器  - 死区控制、边缘/中间对齐波形和紧急制动
■  低功耗  - 2个看门狗定时器(独立的和窗口型的)
-  系统时间定时器:24位的、带自动加载功
- 3种省电模式:睡眠、停机和待机模式
能的
- VBAT为RTC和后备寄存器供电
■  多达9个通信接口
■  2个12位模数转换器,1us转换时间(16通道)
-  多达2个I2C接口(SMBus/PMBus)
-  转换范围是0至3.6V
-  多达3个USART接口,支持ISO7816,
-  双采样和保持功能
LIN,IrDA接口和调制解调控制
-  温度传感器
-  多达2个SPI同步串行接口(18兆位/秒)
■  调试模式
- CAN接口(2.0B 主动)
-  串行线调试(SWD)和JTAG接口
- USB 2.0全速接口
■  DMA
■  ECOPACK(R)封装(兼容RoHS)
- 7通道DMA控制器
 
-  支持的外设:定时器、ADC、SPI、I2C和
表一  器件列表
USART
参 考  基本型号
■  多达80个快速I/O口
STM32F103x6 STM32F103C6, STM32F103R6,
- 26/36/51/80个多功能双向5V兼容的I/O口
STM32F103T6
-  所有I/O口可以映像到16个外部中断

点击此处查看原文 >>

系统分类: ARM   |    用户分类:    |    来源: 原创

评论(0) | 阅读(442)
发表于:2008-4-26 17:17:43
标签:EK-STM32的串口错误  

0

万利的EK-STM32F串口 MAX202用错了

我调试几次USART,都发现不通,无法与PC通讯,最后检查了一下硬件,电路原理图上面画的是

ST3232,大家知道3232是3.3V供电就可以,但是万利板子上焊接的是 MAX202,这个与3232管脚兼容,但是注意

MAX202要5V供电,万利太不小心了,我跳了好几天串口.

点击此处查看原文 >>

系统分类: ARM   |    用户分类:    |    来源: 原创

评论(0) | 阅读(305)
发表于:2008-4-23 21:12:12
标签:STM32流水灯  

1

万利STM32板子实现LED流水灯

万利的例子没有流水灯,我把它的ADC工程改了改,可以实现4个LED从左到右循环闪亮,这是整个工程点击下载

点击此处查看原文 >>

系统分类: ARM   |    用户分类:    |    来源: 原创

评论(1) | 阅读(309)
发表于:2008-4-23 20:41:10
标签:PADS中文教程  

3