先把STM32学了,至少知道有些什么硬件资源,资源是怎么控制的;上了操作系统,说白了就和硬件层关系就不那么大了,所有的资源都交给操作系统去管理了,上边写程序都是用操作系统给的函数接口;当然驱动编写是离不开硬件的。所以先要把硬件学会,有硬件基础了,就好办了,刚开始是有些不习惯,因为上操作系统就有些偏软件了,里面有很多操作系统的机制一时还转换不过来。如果觉得理解不了可以先看看操作系统原理,把一些概念理解了。其实无论什么操作系统都是有共同点的,无非就是进程调度,进程间的同步与通信,内存管理和文件系统等等。慢慢的自己移植(现在移植都比较方便的汇编和CPU部分都基本是现成的了,这才是操作系统的根基),把操作系统里面的机制都用一遍,慢慢的就理解了。要相信,没有足够的准备和积累,是吃不下一大块肉的,不要急。
stm32固件库SPI操作
来源: 野火零死角玩转STM32-F407
'''
/* Private typedef -----------------------------------------------------------*/
//#define sFLASH_ID 0xEF3015 //W25X16
//#define sFLASH_ID 0xEF4015 //W25Q16
//#define sFLASH_ID 0XEF4017 //W25Q64
//#define SPI_FLASH_PageSize 4096
/* Private define ------------------------------------------------------------ /
/ 命令定义-开头*******************************/
/*命令定义-结尾*******************************/
/*SPI接口定义-开头****************************/
/*SPI接口定义-结尾****************************/
/ 等待超时时间 /
/ 信息输出 /
==============================
static __IO uint32_t SPITimeout = SPIT_LONG_TIMEOUT;
static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);
/**
/* 使能 FLASH_SPI 及GPIO 时钟 /
/ ! SPI_FLASH_SPI_CS_GPIO, SPI_FLASH_SPI_MOSI_GPIO,
SPI_FLASH_SPI_MISO_GPIO,SPI_FLASH_SPI_SCK_GPIO 时钟使能 */
RCC_AHB1PeriphClockCmd (FLASH_SPI_SCK_GPIO_CLK | FLASH_SPI_MISO_GPIO_CLK|FLASH_SPI_MOSI_GPIO_CLK|FLASH_CS_GPIO_CLK, ENABLE);
/*! SPI_FLASH_SPI 时钟使能 */
FLASH_SPI_CLK_INIT(FLASH_SPI_CLK, ENABLE);
//设置引脚复用
GPIO_PinAFConfig(FLASH_SPI_SCK_GPIO_PORT,FLASH_SPI_SCK_PINSOURCE,FLASH_SPI_SCK_AF);
GPIO_PinAFConfig(FLASH_SPI_MISO_GPIO_PORT,FLASH_SPI_MISO_PINSOURCE,FLASH_SPI_MISO_AF);
GPIO_PinAFConfig(FLASH_SPI_MOSI_GPIO_PORT,FLASH_SPI_MOSI_PINSOURCE,FLASH_SPI_MOSI_AF);
/*! 配置 SPI_FLASH_SPI 引脚: SCK */
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(FLASH_SPI_SCK_GPIO_PORT, GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN;
GPIO_Init(FLASH_SPI_MISO_GPIO_PORT, GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN;
GPIO_Init(FLASH_SPI_MOSI_GPIO_PORT, GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FLASH_CS_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(FLASH_CS_GPIO_PORT, GPIO_InitStructure);
/* 停止信号 FLASH: CS引脚高电平*/
SPI_FLASH_CS_HIGH();
/* FLASH_SPI 模式配置 */
// FLASH芯片 支持SPI模式0及模式3,据此设置CPOL CPHA
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_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(FLASH_SPI, SPI_InitStructure);
/* 使能 FLASH_SPI */
SPI_Cmd(FLASH_SPI, ENABLE);
}
/**
/**
/* 整块 Erase /
/ 选择FLASH: CS低电平 /
SPI_FLASH_CS_LOW();
/ 发送整块擦除指令 /
SPI_FLASH_SendByte(W25X_ChipErase);
/ 停止信号 FLASH: CS 高电平 */
SPI_FLASH_CS_HIGH();
/* 等待擦除完毕*/
SPI_FLASH_WaitForWriteEnd();
}
/**
/* 选择FLASH: CS低电平 /
SPI_FLASH_CS_LOW();
/ 写页写指令 /
SPI_FLASH_SendByte(W25X_PageProgram);
/ 发送写地址的高位 /
SPI_FLASH_SendByte((WriteAddr 0xFF0000) 16);
/ 发送写地址的中位 /
SPI_FLASH_SendByte((WriteAddr 0xFF00) 8);
/ 发送写地址的低位*/
SPI_FLASH_SendByte(WriteAddr 0xFF);
if(NumByteToWrite SPI_FLASH_PerWritePageSize)
{
NumByteToWrite = SPI_FLASH_PerWritePageSize;
FLASH_ERROR("SPI_FLASH_PageWrite too large!");
}
/* 写入数据 /
while (NumByteToWrite--)
{
/ 发送当前要写入的字节数据 /
SPI_FLASH_SendByte( pBuffer);
/* 指向下一字节数据 */
pBuffer++;
}
/* 停止信号 FLASH: CS 高电平 */
SPI_FLASH_CS_HIGH();
/* 等待写入完毕*/
SPI_FLASH_WaitForWriteEnd();
}
/**
/**
/* 发送 读 指令 */
SPI_FLASH_SendByte(W25X_ReadData);
/* 发送 读 地址高位 /
SPI_FLASH_SendByte((ReadAddr 0xFF0000) 16);
/ 发送 读 地址中位 /
SPI_FLASH_SendByte((ReadAddr 0xFF00) 8);
/ 发送 读 地址低位 */
SPI_FLASH_SendByte(ReadAddr 0xFF);
while (NumByteToRead--)
{
/* 读取一个字节*/
pBuffer = SPI_FLASH_SendByte(Dummy_Byte);
/ 指向下一个字节缓冲区 */
pBuffer++;
}
/* 停止信号 FLASH: CS 高电平 */
SPI_FLASH_CS_HIGH();
}
/**
/* 开始通讯:CS低电平 */
SPI_FLASH_CS_LOW();
/* 发送JEDEC指令,读取ID */
SPI_FLASH_SendByte(W25X_JedecDeviceID);
/* 读取一个字节数据 */
Temp0 = SPI_FLASH_SendByte(Dummy_Byte);
/* 读取一个字节数据 */
Temp1 = SPI_FLASH_SendByte(Dummy_Byte);
/* 读取一个字节数据 */
Temp2 = SPI_FLASH_SendByte(Dummy_Byte);
/* 停止通讯:CS高电平 */
SPI_FLASH_CS_HIGH();
Temp = (Temp0 16) | (Temp1 8) | Temp2;
return Temp;
}
/**
/* Select the FLASH: Chip Select low */
SPI_FLASH_CS_LOW();
/* Send "RDID " instruction */
SPI_FLASH_SendByte(W25X_DeviceID);
SPI_FLASH_SendByte(Dummy_Byte);
SPI_FLASH_SendByte(Dummy_Byte);
SPI_FLASH_SendByte(Dummy_Byte);
/* Read a byte from the FLASH */
Temp = SPI_FLASH_SendByte(Dummy_Byte);
/* Deselect the FLASH: Chip Select high */
SPI_FLASH_CS_HIGH();
return Temp;
}
/*******************************************************************************
/**
/**
/* 等待发送缓冲区为空,TXE事件 */
while (SPI_I2S_GetFlagStatus(FLASH_SPI, SPI_I2S_FLAG_TXE) == RESET)
{
if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(0);
}
/* 写入数据寄存器,把要写入的数据写入发送缓冲区 */
SPI_I2S_SendData(FLASH_SPI, byte);
SPITimeout = SPIT_FLAG_TIMEOUT;
/* 等待接收缓冲区非空,RXNE事件 */
while (SPI_I2S_GetFlagStatus(FLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET)
{
if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(1);
}
/* 读取数据寄存器,获取接收缓冲区数据 */
return SPI_I2S_ReceiveData(FLASH_SPI);
}
/*******************************************************************************
/**
/* 发送写使能命令*/
SPI_FLASH_SendByte(W25X_WriteEnable);
/*通讯结束:CS高 */
SPI_FLASH_CS_HIGH();
}
/**
/* 选择 FLASH: CS 低 */
SPI_FLASH_CS_LOW();
/* 发送 读状态寄存器 命令 */
SPI_FLASH_SendByte(W25X_ReadStatusReg);
SPITimeout = SPIT_FLAG_TIMEOUT;
/* 若FLASH忙碌,则等待 /
do
{
/ 读取FLASH芯片的状态寄存器 */
FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);
}
while ((FLASH_Status WIP_Flag) == SET); /* 正在写入标志 */
/* 停止信号 FLASH: CS 高 */
SPI_FLASH_CS_HIGH();
}
//进入掉电模式
void SPI_Flash_PowerDown(void)
{
/* 选择 FLASH: CS 低 */
SPI_FLASH_CS_LOW();
/* 发送 掉电 命令 */
SPI_FLASH_SendByte(W25X_PowerDown);
/* 停止信号 FLASH: CS 高 */
SPI_FLASH_CS_HIGH();
}
//唤醒
void SPI_Flash_WAKEUP(void)
{
/*选择 FLASH: CS 低 */
SPI_FLASH_CS_LOW();
/* 发上 上电 命令 */
SPI_FLASH_SendByte(W25X_ReleasePowerDown);
/* 停止信号 FLASH: CS 高 */
SPI_FLASH_CS_HIGH(); //等待TRES1
}
/**
==============================
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
while(BufferLength--)
{
if(*pBuffer1 != *pBuffer2)
{
return FAILED;
}
}
return PASSED;
}
void Delay(__IO uint32_t nCount)
{
for(; nCount != 0; nCount--);
}
//main
/* 16M串行flash W25Q128初始化 */
SPI_FLASH_Init();
'''
神州的技术支持不怎么样,,,野火的没听说过好或不好。。。奋斗,火牛听说都不错,开发板就那样,各有优缺点...
我手里三块开发板,一个是南京万利的EK_STM3210E,基本就是copy的官方板,资料很少,更别提售后了,也没有技术支持,教程就是ST的例程,绝对的买亏了;
还有自己买的ALIENTEK mini开发板,价格不高,但是资料很多,原创的教程绝对推荐,而且还出了书,售后也没得说,有问题发论坛,很快有人回复,不足的是板子的芯片cpu配置有点低,但是入门是足够了的,各种接口,串口、i2c、spi、usb都有,还有红外,sd卡,触摸屏等等,文件系统,ucos嵌入系统,gui系统等也都有涉及到,我就是用它入门的,不得不说,没选错;
再就是跟同学借的安富莱开发板,板载配置没得说,与mini板相比,cpu配置高,还多了usb host,wm8978音频芯片、vs1003解码器(喇叭,板载麦克,耳机),还有示波器探头,ps/2键盘接口等,凡是板子上有的芯片都有配套的例程,很不错,就是售后论坛不大给力,有问题还是跑mini板的论坛;
另外除了mini板是操作寄存器,貌似所有的开发板都是使用库函数的教程,其实是一回事,写程序不可能都用库函数,但也不能不参考库函数,略提一下。不管买哪个开发板,正点原子的stm32不完全手册(电子版是这个名,书好像是叫例说stm32)都推荐看下...
ucos|4-ucosII|卢老师|UCOSII|源享科技ucosd操作系统百度网盘免费资源在线学习
链接:
提取码: 599i
ucos 4-ucosII 卢老师 UCOSII 源享科技ucosd操作系统.zip UCOS视频教程王华斌.rar UCOS移植资料 如何学习嵌入式开发.rar 零死角玩转stm32-系统篇1、uCOS-II 移植与深入实战指南.pdf 基于嵌入式实时操作系统的程序设计技术+周航慈.pdf 北航uCOS-II课件.pdf VC6.0 UCGUI3.90源码.zip uCOSⅡ中文教程(邵贝贝).pdf ucosii.rar uCOS2精华快速掌握.ppt
stm32移植ucos系统后,就可以更好的管理内存;
ucos是一种免费公开源代码、结构小巧、具有可剥夺实时内核的实时操作系统。
STM32系列基于专为要求高性能、低成本、低功耗的嵌入式应用专门设计的ARM
Cortex-M内核。
本文标签:零死角玩转stm32ucos