by HYH | 2017 年 9 月 13 日 下午 10:22

一.开发板简介

开发板上除了必须的晶振和复位电路,只有一个接在PB12上的led(用于测试)。

二.串口下载(stm32flash)

1.下载及安装。

官方下载:https://sourceforge.net/projects/stm32flash/files/(windows下载:stm32flash-0.5-win64.zip ,Linux下载:stm32flash-0.5.tar.gz)

下载地址:stm32flash-0.5.tar

32位 windows版下载地址:stm32flash-win32

解压之后,直接进入文件夹

make

make install

2.下载前的硬件设置.

1)除电源和地外,将USB转串口的RX接到PA9,TX接到PA10.

2)Boot0接高电平(正常运行时接低电平),Boot1接低电平。

3)连接完成后,按复位键。

3.常用命令(需root权限)

备份stm32的flash到文件:

stm32flash -r 备份文件名 串口设备名

从文件烧写stm32flash的flash:

stm32flash -w 文件名 串口设备名

4.附加:

由于rtthread的组件finsh组件,改变硬件连接(Boot0接低电平)并按复位键之后,可使用烧写串口调试(直接调用导出给finsh组件的C函数),无需更改串口连接。

调试波特率:115200

5.附加2:

在windows下,串口设备的表示方式为:COMn(n为整数,有时会失败)或 \\.\COMn(n为整数且兼容性更好)

其中n的值由通过设备管理器人工确定。

putty也可在windows下使用:

stm32flash在windows下使用时,需要将stm32flash.exe所在文件夹添加到PATH变量中,或者将stm32flash.exe放到PATH变量中有的目录(C:\windows)当中。运行stm32flash时最好使用管理员权限。如果打开串口失败,检查是否有其它软件(如putty)在使用该串口。

三.RT-thread编译以及简单使用。

1.编译环境搭建(arm-none-eabi-gcc+scons)

1)软件下载:

gcc:https://launchpad.net/gcc-arm-embedded/+download

python:https://www.python.org/downloads/

scons:http://scons.org/pages/download.html

可选软件:notepad++

2)安装注意事项:

gcc

安装过程中记好安装路径:

选择添加PATH变量

python

安装过程中记好安装路径:

选择添加PATH变量:

scons

必选先成功安装python.

安装完成后,手动将 python目录\scripts 添加到PATH变量。

如果能够运行scons即编译环境搭建完成:

2.rt-thread下载及编译前设置

1)下载

下载:http://www.rt-thread.org/page/31.html

http://pan.baidu.com/s/1mgIAyWo

将下载的zip包解压。

2)编译需要用到目录及文件简介(非开发)

examples\:rt-thread的示例。

bsp\:此目录下有rt-thread对各种芯片的支持,根据实际需要进入相应目录运行scons编译。如bsp\stm32f10x就是对stm32f103c6t8的支持,下面是对该目录的介绍:

rtconfig.py:编译工具设置,编译前必须设置好此文件。

rtconfig.h:rt-thread配置。通过注释取消注释来配置rt-thread。其中含有USING字样的为可选组件,可进行裁剪(组件间似乎有依赖关系,修改前最好备份)。

drivers:驱动文件夹,有的文件需要根据芯片实际情况或电路板外围电路情况进行修改。

applications:应用文件夹.其中startup.c为main函数所在文件。application.c包含一个led的任务,其调用的drivers\led.c中的函数控制一个led灯(用于显示正在运行)。

3)文件配置

rtconfig.py

CROSS_TOOL=’gcc’

EXEC_PATH = ‘gcc安装目录/bin'(将路径中的\改为/)

drivers\board.h

#define STM32_SRAM_SIZE 实际内存大小

drivers\led.c

将led1改为PB12(所用开发板在PB12脚连了一个led)

#define led1_rcc RCC_APB2Periph_GPIOB
#define led1_gpio GPIOB
#define led1_pin (GPIO_Pin_12)

4)编译

scons 编译

scons -c 清理编译文件

5)烧录

rtthread.bin为烧录所用文件。

6)附加:

这样编译完成的rt-thread把唯一的一个led给占用了。为了释放这个led,可注释掉

rt_hw_led_init();

rt_hw_led_on(0);

rt_hw_led_off(0);

这样编译的固件,就不会占用led了。

就可使用drivers\led.c导出的led函数控制led了。(不存在led2,只有led1)。

led函数用法:

led(led选择,电平); led选择为1是选择led2,0选择led1.

7).附加2:

finsh简单使用:

list(); 查看已经导出的函数

list_thread(); 查看任务

list_timer();查看定时器

3.RT-thread简单开发

1)添加.c文件并使用FINSH打印字符

有时可能需要自己添加一个.c文件(以在applications\下添加一个app.c为例)。

首先新建一个名为app.c的文本文件。

编辑同目录的SConscript文件,将app.c添加到文件列的顶端。

接下来就是写app.c的内容

因为是用rt-thread开发应用,因此应当包含rtthread.h.

因为FINSH是可选组件,因此要在

#ifdef RT_USING_FINSH
#include <finsh.h>

#endif

之间写程序

然后就是写要导出的函数的主体了

其中rt_kprintf();可用于打印字符,用法跟printf()类似。

最后导出函数

FINSH_FUNCTION_EXPORT(函数名,描述)

注意:由于是宏定义,无须分号。

接下来就是编译

结果:

2)利用pin设备控制GPIO

要使用pin设备必须包含<drivers\pin.h>。

pin设备的引脚号数在stm32f10x下是由低层驱动(drivers\gpio.c)控制的.

如 __STM32_PIN(30, APB2, A, 5),表示30号引脚为PA5。

电平表示方式:

输入输出模式表示方式:

pin设备结构体:

pin输入输出模式结构体:

pin状态结构体:

常用函数:

rt_device_find(“pin”);//获取pin设备指针,返回值为rt_device_t,必须强制转换成rt_device_pin的指针.

rt_device_open(rt_device_pin的指针->parent,RT_NULL);//打开pin设备

rt_device_control(rt_device_pin的指针->parent,RT_NULL,pin输入输出模式结构体的指针);//应用输入输出模式

rt_device_write(rt_device_pin的指针->parent,RT_NULL,pin状态结构体的指针,sizeof(pin状态结构体));//写pin

rt_device_read(rt_device_pin的指针->parent,RT_NULL,pin状态结构体的指针,sizeof(pin状态结构体));//读pin

示例:

app

结果:

4.STM32F10X简单开发

rt-thread自带stm32f10x标准库,不依赖rt-thread.

目录:Libraries\STM32F10x_StdPeriph_Driver

1)GPIO口

GPIO口表示方式:GPIOA GPIOB … GPIOG (实际情况视芯片而定,对应的IO时钟为RCC_APB2Periph_GPIOA,RCC_APB2Periph_GPIOB … RCC_APB2Periph_GPIOG)

针脚表示方式:GPIO_PIN_n(n为数字)

如PA0的GPIO口为GPIOA,针脚为GPIO_PIN_0,IO时钟为RCC_APB2Periph_GPIOA。

要使用GPIO库函数,必须先包含stm32f10x_gpio.h

下面介绍几个常用的函数:

GPIO_ReadInputDataBit(GPIO口,针脚);

读取特定GPIO口的特定针脚。

GPIO_ReadInputData(GPIO口);

读取GPIO口

GPIO_ResetBits(GPIO口,针脚);

设置某个针脚为0

GPIO_SetBits(GPIO口,针脚);

设置某个针脚为1

下面是初始化示例代码:

GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(IO时钟,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO模式;
GPIO_InitStructure.GPIO_Speed = GPIO速度;
GPIO_InitStructure.GPIO_Pin = 针脚;
GPIO_Init(GPIO口, &GPIO_InitStructure);

其中GPIO口,针脚,资源名可通过|号一次初始多个(如GPIO_PIN0|GPIO_PIN_1表示两个都初始化)

GPIO模式:

GPIO速度:

示例:

app

结果:

PA1接PA0(后三个命令)

用万用表测试PA1的电平变化也正确。

2)ADC示例(ADC1通道5)

app

代码:

#include <rtthread.h>
#include “stm32f10x_adc.h”
#ifdef RT_USING_FINSH
#include <finsh.h>

void ADC_Config(void) //ADC初始化
{
ADC_InitTypeDef ADC_1; //初始化结构体声明
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); //开启ADC1时钟,ADC2为RCC_APB2Periph_ADC1

ADC_StructInit(&ADC_1);//导入默认配置:独立模式,不扫描,不连续转换,TIM1_CC1事件触发,右对齐,通道数1
ADC_1.ADC_ScanConvMode = ENABLE;//开启扫描模式
ADC_1.ADC_ContinuousConvMode = ENABLE;//开启连续扫描模式
ADC_1.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发

ADC_Init(ADC1,&ADC_1); //初始化ADC1
ADC_RegularChannelConfig(ADC1,ADC_Channel_5,1,ADC_SampleTime_55Cycles5);//通道组,设置第五个通道的顺序为1,采样时间55.5周期

}

void GPIO_Config()//GPIO初始化,主要把ADC输入通道所在引脚配置为模拟输入模式
{
GPIO_InitTypeDef PA5;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIOA时钟
PA5.GPIO_Pin=GPIO_Pin_5;//第五引脚
PA5.GPIO_Mode=GPIO_Mode_AIN;//模拟输入模式

GPIO_Init(GPIOA,&PA5);//初始化PA5

}

void adctest()
{
uint16_t ad_v=0;//保存转换结果的变量
GPIO_Config();//调用GPIO初始化
ADC_Config();//调用ADC初始化

ADC_Cmd(ADC1,ENABLE);//开启ADC1
ADC_ResetCalibration(ADC1);//重置ADC1校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));//等待重置完成
ADC_StartCalibration(ADC1);//开始校准ADC1
while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
ADC_SoftwareStartConvCmd(ADC1,ENABLE);//开始软件触发
rt_kprintf(“start adc1(Channel_5)\n”);//调用finsh组件
while(1)
{
rt_thread_delay( RT_TICK_PER_SECOND/2 ); /* 睡眠0.5秒(RTthread功能) */

ad_v=ADC_GetConversionValue(ADC1);//获取最近的转换值
ad_v&=0x0fff;//保留右对齐的12位
rt_kprintf(“ADC1:%d\n”,ad_v);//调用finsh打印结果
}

}
FINSH_FUNCTION_EXPORT(adctest,test adc (pa5))
#endif

包含文件:stm32f10x_adc.h

通道号数由引脚第二功能决定(如PA5的第二功能是ADC_IN5,所以它是通道5)

示例结果:

3)UASRT(UART2查询方式)

app

#include <rtthread.h>
//#include <rtdevice.h>
//#include <drivers\serial.h>
#include <stm32f10x_usart.h>
#ifdef RT_USING_FINSH
#include <finsh.h>
void uartinit()//初始化GPIO,UART2
{
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE);//打开UART2时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO,ENABLE);//打开GPIOA(UART2所在GPIO口)时钟

GPIO_InitTypeDef GPIO_InitStructure;//GPIO初始化结构体

/*设置USART2 Tx(PA.2)*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*设置USART2 Rx(PA.3) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);

USART_InitTypeDef USART_InitStructure;//UASRT初始化结构体

USART_InitStructure.USART_BaudRate = 9600; //波特率9600
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据位8位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1位
USART_InitStructure.USART_Parity = USART_Parity_No; //无校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不开启流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //收发模式
USART_Init(USART2, &USART_InitStructure);//初始化UASRT2
USART_Cmd(USART2, ENABLE); //启动UASRT2

}
void testuart()
{

uartinit();
while(1)
{
USART2->SR;//防止第一个字符被忽略
while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET);//等待接收完成
USART_SendData(USART2, USART_ReceiveData(USART2));//发送接收的数据
while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待发送完成

}

}

FINSH_FUNCTION_EXPORT(testuart,uart2 test)
#endif

必须包含头文件:stm32f10x_usart.h

实验结果:

4)i2c(I2C1)

i2c的从硬件是PCF8591(8位AD/DA转换器)

app

#include <rtthread.h>
#include “stm32f10x_adc.h”
#ifdef RT_USING_FINSH
#include <finsh.h>

void i2c_init()//i2c初始化设置
{
I2C_InitTypeDef I2C_Struct;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
I2C_StructInit(&I2C_Struct);
I2C_Struct.I2C_ClockSpeed=100000;
I2C_Struct.I2C_Mode=I2C_Mode_I2C ;
I2C_Struct.I2C_DutyCycle=I2C_DutyCycle_2;
I2C_Struct.I2C_Ack=I2C_Ack_Enable; //使能应答位
I2C_Struct.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit ;
I2C_Init( I2C1, &I2C_Struct);

I2C_Cmd(I2C1,ENABLE);

}
void gpio_init()//设置i2c引脚
{
GPIO_InitTypeDef GPIO_Struct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOB,ENABLE);

GPIO_Struct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
GPIO_Struct.GPIO_Mode=GPIO_Mode_AF_OD;
GPIO_Struct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_Struct);
}
void I2C_WaitEepromStandbyState(u8 id) //防守函数,非常重要
{
vu16 SR1_Tmp = 0;

do
{
/* Send START condition */
I2C_GenerateSTART(I2C1, ENABLE);
/* Read I2C1 SR1 register */
SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);
/* Send EEPROM address for write */
I2C_Send7bitAddress(I2C1, id, I2C_Direction_Transmitter);
}while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002)); //estimate the value of ADDR

/* Clear AF flag */
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
}
void i2c_write(u8 id,u8 address,u8 byte)//I2C写函数,参数依次是id,地址,要写入的值。(均是8位)
{
I2C_WaitEepromStandbyState(id);
I2C_GenerateSTART ( I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //ev5
I2C_Send7bitAddress ( I2C1,id, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED )); //ev6
I2C_SendData ( I2C1, address);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //ev8
I2C_SendData ( I2C1, byte);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //ev8_2
I2C_GenerateSTOP(I2C1, ENABLE);
}
u8 i2c_read(u8 id,u8 address)//i2c读函数,参数依次是id,地址。(均是8位)
{
u8 temp;
I2C_WaitEepromStandbyState(id);
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
I2C_AcknowledgeConfig(I2C1, DISABLE); //
I2C_Send7bitAddress ( I2C1,id, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData ( I2C1, address);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING));
I2C_GenerateSTART(I2C1, ENABLE); //restart
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //ev5
I2C_Send7bitAddress ( I2C1,id, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //ev6
I2C_GenerateSTOP(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)); //ev7
temp=I2C_ReceiveData(I2C1);

return temp;
}
int testi2c(void)
{
u8 data[5];//定义数组用于储存8位AD结果
gpio_init();
rt_kprintf(“GPIO init\n”);
i2c_init();
rt_kprintf(“start i2c\n”);
while(1)//读取pcf8591,A0=A1=A2=0
{
rt_thread_delay( RT_TICK_PER_SECOND/10 ); //睡眠0.1秒,读取过快可能引起死机.
data[0]=i2c_read(0x91,0x40);//读取通道0
data[1]=i2c_read(0x91,0x41);//读取通道1
data[2]=i2c_read(0x91,0x42);//读取通道2
data[3]=i2c_read(0x91,0x43);//读取通道3
data[4]=data[0];
i2c_write(0x90,0x40,data[4]);//DA转换
rt_kprintf(“\radc:%d %d %d %d\t\t”,data[0],data[1],data[2],data[3]);//打印AD结果
}
}
FINSH_FUNCTION_EXPORT(testi2c,test i2c)
#endif

必须包含的头文件:stm32f10x_adc.h

结果:

https://hyhsystem.cn/wordpress/


转载于:https://www.cnblogs.com/HEYAHONG/p/8393448.html

STM32F10x随笔(gcc+scons)相关推荐

  1. 在windows下如何配置RTT开发环境?

    之前一直使用MDK查看和编译RTT的源码,这几天无聊想起RTT官方提供使用scons工具编译RTT,因此想试试这种方法,做下此笔记,以供入门者参考. 注: 这里MDK的安装目录千万不能包含空格(比如: ...

  2. 1231_使用SCons实现多目录多文件且跨目录引用的编译环境搭建(linux + gcc)

    全部学习汇总: GitHub - GreyZhang/g_SCons: A new member in my toolbox, looking forward to replacing make to ...

  3. SCons 构建工具

    SCons 简介 SCons 是一套由 Python 语言编写的开源构建系统,类似于 GNU Make.它采用不同于通常 Makefile 文件的方式,而是使用 SConstruct 和 SConsc ...

  4. 使用 SCons 轻松建造程序

    原文:http://www.ibm.com/developerworks/cn/linux/l-cn-scons/index.html 参考:http://www.flatws.cn/article/ ...

  5. SCons — 程序构建工具

    目录 文章目录 目录 SCons - a software construction tool 使用示例 SCons - a software construction tool SCons 类似于 ...

  6. linux内核使用scons构建,如何使用scons进行交叉构建

    我正在尝试创建最简单的可想象的SConstruct文件,用于交叉编译程序. 我尝试了不同的设置,最新的SConstruct文件在这里: env_options = { "CC" : ...

  7. STM32高级开发(12)-在GCC中使用printf打印串口数据

    在大家使用keil或是iar开发stm32等arm芯片的时候,想来最不陌生的就是使用print通过串口输出一些数据,用来调试或是其他作用.但是要明确的是由于keil iar gcc 他们使用的标准C语 ...

  8. buntu linux下建立stm32开发环境: GCC安装以及工程Makefile建立

    之前在e络盟的意法半导体掏了一个STM32开发板挺好的,却不想在window下开发,也不想用那么占内存的IAR MDK等软件,所以决定在ubuntu下建立该开发环境,像之前avr linux一样,找了 ...

  9. c语言项目为什么要build?(gcc、makefile、cmake(qmake)、CMakeLists.txt)(qmake、cmake、qbs区别解析)(qmake还是cmake,mingw作用)

    搞不太懂gcc和cmake(qmake)等的区别 1.gcc是GNU Compiler Collection(就是GNU编译器套件),也可以简单认为是编译器, 它可以编译很多种编程语言(括C.C++. ...

最新文章

  1. 【ASP.NET Core】处理异常(上篇)
  2. iPhonexr安兔兔html5测试,给大家科普下iphonexr苹果手机安兔兔跑分多少分
  3. php正则过滤html标签_空格_换行符的代码,PHP 正则过滤 html 标签、空格、换行符的代码 (文章格式化)...
  4. Drawing with GoogLeNet
  5. utilities(C/C++)(二)
  6. 微信小程序MQTT客户端的坑
  7. 惊了!一个程序员的水平能差到什么程度
  8. QT等待动态图gif加载透明背景lable
  9. 14届数独-真题标准数独-Day 7-20220122
  10. 透视效果的十字路口,不再“亲人两行泪”
  11. 计算机培训excel的制作,绵阳电脑excel表格制作教程
  12. 短链(ShortURL)的Java实现
  13. 【Python模块】图形化编程模块-turtle
  14. oppo R9sk 完美root 线刷包+救砖
  15. Windows日志分析(上)
  16. 北京地铁背景音乐曲目
  17. Hexo+Github: 博客网站搭建完全教程(看这篇就够了)
  18. Error in DESeqDataSet(se, design = design, ignoreRank) : some values in assay are negative
  19. 102_Hadoop常用命令
  20. 嵌入式audio基础(八)主动降噪

热门文章

  1. 使用cocopods安装Alamofire后各种报错
  2. Ubuntu 12.04下配置JDK7
  3. VS调试时断点无法进入或命中的原因及解决方法(PDB引发的)
  4. android中将日志文件输出到sd卡
  5. silverlight 加载大图片进度提示
  6. DataGrid多层表头设计
  7. (8)FPGA实现1s闪灯代码(学无止境)
  8. java 空的构造函数_用javassist创建空的构造函数(java)不能上班
  9. linux文档查看器翻译,mdv – Linux终端下的 Markdown 文档查看器
  10. matplotlib安装失败_Python | 安装中遇到“0x80072f7d 未指定的错误”