这里我会记录我接下来所使用过的所有代码,弄成一个一个函数、供自己以后复习、贴代码。
1、点亮LED灯(流水灯)
#include "stm32f10x.h"
void delay_ms(int t);
void LED_Init();
int i, j;
int main(void)
{
LED_Init();
while(1){
GPIOA->BSRR = 0x01000000; // 置 0
delay_ms(500);
GPIOA->BSRR = 0x00000100; // 置 1
GPIOD->BSRR = 0x00040000; // 置0
delay_ms(500);
GPIOD->BSRR = 0x00000004; // 置 1
}
}
void LED_Init()
{
RCC->APB2ENR|=1<<2; //开启PORTA时钟使能
RCC->APB2ENR|=1<<5; //开启PORTD时钟使能
GPIOA->CRH&=0xFFFFFFF0;
GPIOA->CRH|=0X00000003;//PA.8 通用推挽输出
GPIOA->BSRR=0x00000100; // PA.8 置1
GPIOD->CRL&=0xFFFFF0FF;
GPIOD->CRL|=0X00000300;//PD.2 通用推挽输出
GPIOD->BSRR=0x00000004; // PD.2 置1
}
void delay_ms(int t) // 啥也不干就是浪费时间
{
for(i = 0; i < t; i++){
for(j = 0; j < 1000; j++){
}
}
}
2、通过调用库函数实现LED流水灯
#include "stm32f10x.h"
void delay_ms(int t);
void LED_Init();
void RCC_Configuration(void);
int i, j;
int main(void)
{
LED_Init();
while(1){
GPIO_SetBits(GPIOA,GPIO_Pin_8); // PA.8
delay_ms(500);
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
GPIO_SetBits(GPIOD,GPIO_Pin_2); // PD.2
delay_ms(500);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
}
void LED_Init()
{
GPIO_InitTypeDef GPIO_InitStructure; // 声明GPIO初始化结构变量
RCC_Configuration(); // 配置时钟
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // IO口配置为推挽输出口
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 频率为50HZ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; // 配置管脚8
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化PA8口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // 配置管脚2
GPIO_Init(GPIOD, &GPIO_InitStructure); // 初始化PD2口
}
void RCC_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); // 使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); // 使能GPIOD时钟
}
void delay_ms(int t) // for循环浪费时间的延时
{
for(i = 0; i < t; i++){
for(j = 0; j < 1000; j++){
}
}
}
3、实验内容(点一个键、一个灯闪烁两下,另一个灯闪烁一下,反之亦然)
#include "stm32f10x.h"
#define KEY_ON 0
#define KEY_OFF 1
void delay_ms(int t);
void Init();
void GPIO_Configuration(void);
uint8_t KeyScan( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin_x );
int i, j;
char flag = 0;
int main(void)
{
Init();
while(1){
if(KeyScan( GPIOC, GPIO_Pin_5 ) == KEY_ON)// 按下 key0 时 (PC.5)
{
flag = 0;
}else if(KeyScan( GPIOA, GPIO_Pin_15 ) == KEY_ON) // 按下 key1时 (PA.15)
{
flag = 1;
}
if(flag)
{
GPIO_SetBits(GPIOA,GPIO_Pin_8); // PA.8 灭,
GPIO_ResetBits(GPIOD,GPIO_Pin_2); // PD.2 亮
delay_ms(500);
GPIO_SetBits(GPIOD,GPIO_Pin_2); // PD.2
delay_ms(500);
GPIO_ResetBits(GPIOD,GPIO_Pin_2); // PD.2
delay_ms(500);
GPIO_ResetBits(GPIOA,GPIO_Pin_8); // PA.8
GPIO_SetBits(GPIOD,GPIO_Pin_2); // PD.2
delay_ms(500);
}
else
{
GPIO_SetBits(GPIOD,GPIO_Pin_2); // PD.2
GPIO_ResetBits(GPIOA,GPIO_Pin_8); // PA.8
delay_ms(500);
GPIO_SetBits(GPIOA,GPIO_Pin_8); // PA.8
delay_ms(500);
GPIO_ResetBits(GPIOA,GPIO_Pin_8); // PA.8
delay_ms(500);
GPIO_ResetBits(GPIOD,GPIO_Pin_2); // PD.2
GPIO_SetBits(GPIOA,GPIO_Pin_8); // PA.8
delay_ms(500);
}
}
}
void Init()
{
GPIO_InitTypeDef GPIO_InitStructure; // 声明GPIO结构变量
GPIO_Configuration(); // 配置时钟,(下面的函数)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // IO 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 频率50HZ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; // 配置管脚8
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化PA8口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // 配置管脚2
GPIO_Init(GPIOD, &GPIO_InitStructure); // 初始化PD2口
GPIO_SetBits(GPIOA,GPIO_InitStructure.GPIO_Pin);
GPIO_SetBits(GPIOD,GPIO_InitStructure.GPIO_Pin); // 灯都关闭
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // 配置管脚5
GPIO_Init(GPIOC, &GPIO_InitStructure); // 初始化PC.5口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; // 配置管脚15
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化PA.15口
}
void GPIO_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); // 使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); // 使能GPIOD时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); // 使能GPIOC时钟
}
void delay_ms(int t) // for 循环延时
{
for(i = 0; i < t; i++){
for(j = 0; j < 1000; j++){
}
}
}
static void KeyDelay( uint32_t nCounter ) // 延时 函数
{
while ( nCounter-- );
}
uint8_t KeyScan( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin_x )
{
if ( GPIO_ReadInputDataBit( GPIOx, GPIO_Pin_x ) == KEY_ON ) // 检测是否有按键按下
{
KeyDelay(0x57E40); // 延时消抖
if ( GPIO_ReadInputDataBit( GPIOx, GPIO_Pin_x ) == KEY_ON )
{
while ( GPIO_ReadInputDataBit( GPIOx, GPIO_Pin_x ) == KEY_ON ); // 等待按键释放
return KEY_ON;
}
else
{
return KEY_OFF;
}
}
return KEY_OFF;
}
4、3的通过寄存器控制完成(延时消抖没有添加)(感谢老师(╯﹏╰))
#include "stm32f10x.h"
void delay_ms(int t);
void Init();
void GPIO_Configuration(void);
int i, j;
char flag = 0; // 标记
int main(void)
{
Init();
while(1){
if(~GPIOC->IDR & 1 << 5) // 按下 key1 (PA15)
{
flag = 0;
}else if(~GPIOA->IDR & 1 << 15) // 按下0 (PC5)
{
flag = 1;
}
if(flag)
{
GPIOA->BSRR = 0x01000000; // 置 0
delay_ms(500);
GPIOA->BSRR = 0x00000100; // 置 1
delay_ms(500);
GPIOA->BSRR = 0x01000000; // 置 0
delay_ms(500);
GPIOA->BSRR = 0x00000100; // 置 1
GPIOD->BSRR = 0x00040000; // 置 0
delay_ms(500);
GPIOD->BSRR = 0x00000004; // 置 1
}else
{
GPIOD->BSRR = 0x00040000; // 置 0
delay_ms(500);
GPIOD->BSRR = 0x00000004; // 置 1
delay_ms(500);
GPIOD->BSRR = 0x00040000; // 置 0
delay_ms(500);
GPIOD->BSRR = 0x00000004; // 置 1
GPIOA->BSRR = 0x01000000; // 置 0
delay_ms(500);
GPIOA->BSRR = 0x00000100; // 置 1
}
}
}
void Init()
{
RCC->APB2ENR|=1<<2; //使能PORTA时钟
RCC->APB2ENR|=1<<4; //使能PORTC时钟
RCC->APB2ENR|=1<<5; //使能PORTD时钟
GPIOA->CRH&=0xFFFFFFF0;
GPIOA->CRH|=0X00000003;//PA.8 推挽输出
GPIOA->BSRR=0x00000100; // PA.8 置1
GPIOD->CRL&=0xFFFFF0FF;
GPIOD->CRL|=0X00000300;//PD.2 推挽输出
GPIOD->BSRR=0x00000004; // PD.2 置1
GPIOC->CRL&=0XFFF0FFFF;
GPIOC->CRL|=0X00040000;//PC.5 浮空输入
GPIOA->CRH&=0x0FFFFFFF;
GPIOA->CRH|=0X40000000;//PA.15 浮空输入
}
void GPIO_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); // 使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); // 使能GPIOD时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); // 使能GPIOC时钟
}
void delay_ms(int t) // 延时
{
for(i = 0; i < t; i++){
for(j = 0; j < 1000; j++){
}
}
}
5、静态数码管:
#include"stm32f10x.h"
unsigned char LED7Code[] =
{~0x3F,~0x06,~0x5B,~0x4F,
~0x66,~0x6D,~0x7D,~0x07,
~0x7F,~0x6F,~0x77,~0x7C,
~0x39,~0x5E,~0x79,~0x71,
}; // 0 -> 9 只需要9个
u8 Count = 0;
void RCC_Configuration(void);
void delay_nms(u16 time);
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_Configuration();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 设置为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 工作频率
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure); // 给 GPIOB 赋予上述属性
GPIO_SetBits(GPIOB,GPIO_InitStructure.GPIO_Pin); // 打开这些管脚
while(1)
{
Count++;
GPIO_Write(GPIOB,LED7Code[Count%10]<<8); // 0 -> 9 循环
delay_nms(500);
}
}
void RCC_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); // 使能时钟、
}
void delay_nms(u16 time)
{
u16 i=0;
while(time--)
{
i=12000;
while(i--);
}
}
6、动态数码管:(*^__^*) 谢谢大家的关注,
#include"stm32f10x.h"
#define LS138A GPIO_Pin_5 // 宏
#define LS138B GPIO_Pin_6
#define LS138C GPIO_Pin_7
#define LS138a(x) x ? GPIO_SetBits(GPIOB, LS138A):GPIO_ResetBits(GPIOB, LS138A) // x为1否?1 执行前面的,0,执行后面的
#define LS138b(x) x ? GPIO_SetBits(GPIOB, LS138B):GPIO_ResetBits(GPIOB, LS138B)
#define LS138c(x) x ? GPIO_SetBits(GPIOB, LS138C):GPIO_ResetBits(GPIOB, LS138C)
u8 Count;
u16 Count0;
unsigned long D[16], LedOut[8];
unsigned char Disp_Tab[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x40}; // 数码管显示、
void RCC_Configuration(void);
void GPIO_Configuration(void);
void delay_nms(u16 time);
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
while(1)
{
unsigned char i;
Count++;
if(Count==100)
{
Count0++;
Count=0;
}
D[1] = D[0] = Count0;
LedOut[0] = Disp_Tab[D[1]%10000/1000]; // 千
LedOut[1] = Disp_Tab[D[1]%1000/100]; // 百
LedOut[2] = Disp_Tab[D[1]%100/10]|0x80; // 十
LedOut[3] = Disp_Tab[D[1]%10]; // 个
LedOut[4] = Disp_Tab[D[0]%10000/1000]; // 千
LedOut[5] = Disp_Tab[D[0]%1000/100]; // 百
LedOut[6] = Disp_Tab[D[0]%100/10]|0x80; // 十
LedOut[7] = Disp_Tab[D[0]%10]; // 个
for(i=0; i<8; i++)
{
GPIO_Write(GPIOB, LedOut[i]<<8); // 位操作 <<8(低八位->高八位)
switch(i) // 1,3,8 译码器
{
case 0: LS138c(0); LS138b(0); LS138a(0); break; // 0 0 0
case 1: LS138c(0); LS138b(0); LS138a(1); break; // 1 0 0
case 2: LS138c(0); LS138b(1); LS138a(0); break; // 0 1 0
case 3: LS138c(0); LS138b(1); LS138a(1); break; // 1 1 0
case 4: LS138c(1); LS138b(0); LS138a(0); break; // 0 0 1
case 5: LS138c(1); LS138b(0); LS138a(1); break; // 1 0 1
case 6: LS138c(1); LS138b(1); LS138a(0); break; // 0 1 1
case 7: LS138c(1); LS138b(1); LS138a(1); break; // 1 1 1
}
delay_nms(1);
}
}
}
void RCC_Configuration(void)
{
SystemInit(); // 72HMHZ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB时钟
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_Init(GPIOB,&GPIO_InitStructure); //给 GPIOB 赋予上述属性(8 -> 15)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; // 管脚5,,6,7
GPIO_Init(GPIOB,&GPIO_InitStructure); // 再次给GPIOB赋予上述属性(5,6,7)
GPIO_SetBits(GPIOB,GPIO_InitStructure.GPIO_Pin); // 置位
}
void delay_nms(u16 time)
{
u16 i=0;
while(time--)
{
i=1000;
while(i--);
}
}
7、4*4矩阵键盘
#include "stm32f10x.h"
#define uchar unsigned char
#define uint unsigned int
int keyscan();
void delay_nms(u16 time);
void GPIO_Configuration(void);
unsigned char LED7Code[] = {~0x3F, ~0x06, ~0x5B, ~0x4F,
~0x66, ~0x6D, ~0x7D, ~0x07,
~0x7F, ~0x6F, ~0x77, ~0x7C,
~0x39, ~0x5E, ~0x79, ~0x71}; // 0 - F 的数码管显示
int x;
uchar temp;
uchar key;
u16 ReadedData;
int main(void)
{
GPIO_Configuration();
while(1)
{
x = keyscan();
if(x >= 0)
{
GPIO_Write(GPIOA, LED7Code[x] << 8);
}
}
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure; // 声明GPIO初始化结构变量、
// 使能APB2总线外设时钟、
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 开启PB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 开启PA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 开启复用IO时钟
// ↓ PB3和PB4被用在JTAG接口中,把这两个管脚释放出来,作为普通IO口
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
GPIO_InitStructure.GPIO_Pin =
GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 |
GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输出模式下 i/0输出的速度
GPIO_Init(GPIOA, &GPIO_InitStructure); // PA口初始化
GPIO_Write(GPIOA, LED7Code[8] << 8); // 七段数码管全部点亮、
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 |
GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // I/O口输出速度
GPIO_Init(GPIOB, &GPIO_InitStructure); // PB口初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 |
GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
int keyscan()
{
temp = 0;
GPIO_Write(GPIOB, 0xFFF0); // PB3-PB0 输出低电平
if((GPIOB->IDR & 0x00F0) == 0x00F0) // PB7-PB4全为1,表明没有按键按下,返回-1
{
return -1;
}
else
{
delay_nms(5); // 延时去抖
if((GPIOB->IDR & 0x00F0) == 0x00F0) // 抖动产生的、
{
return -1;
}
}
GPIO_Write(GPIOB, 0xFFFE); // PB3 = PB2 = PB1 = 1、PB0 = 0
temp = ~(GPIOB->IDR | 0xFF0F);
switch(temp) // 对PB7-PB4的值进行判断,
{
case 0x0010 : key = 0; break;
case 0x0020 : key = 1; break;
case 0x0040 : key = 2; break;
case 0x0080 : key = 3; break;
}
GPIO_Write(GPIOB, 0xFFFD); // PB2 = 0,PB0 = PB1 = PB3 = 1
temp = ~(GPIOB->IDR | 0xFF0F);
switch(temp) // 对PB7-PB4的值进行判断,
{
case 0x0010 : key = 4; break;
case 0x0020 : key = 5; break;
case 0x0040 : key = 6; break;
case 0x0080 : key = 7; break;
}
GPIO_Write(GPIOB, 0xFFFB); // PB3 = PB 1 = PB0 = 1, PB2 = 0
temp = ~(GPIOB->IDR | 0xFF0F);
switch(temp)
{
case 0x0010 : key = 8; break;
case 0x0020 : key = 9; break;
case 0x0040 : key = 10; break;
case 0x0080 : key = 11; break;
}
GPIO_Write(GPIOB, 0xFFF7); // PB3 = 0, PB2 = PB1 = PB0 = 1,
temp = ~(GPIOB->IDR | 0xFF0F);
switch(temp)
{
case 0x0010 : key = 12; break;
case 0x0020 : key = 13; break;
case 0x0040 : key = 14; break;
case 0x0080 : key = 15; break;
}
return key;
}
void delay_nms(u16 time)
{
u16 i = 0;
while(time--)
{
i = 12000;
while(i--);
}
}
8、lcd显示
lcd_1602.h
/* LCD1602.h*/
#ifndef __LCD1602_H
#define __LCD1602_H
#define uchar unsigned char
#define uint unsigned int
#define uint unsigned int
void delay(uint a); //延时函数,空循环函数
void delay_ms(uint time); //毫秒级延时
void delay_us(uint time); //微秒级延时
void enable(uchar del); //使能LCD,按时序的底层驱动
void write(uchar del); //写LCD,按时序的底层驱动
void L1602_init(void); //1602初始化
void L1602_char(uchar row, uchar column,char sign); //按行列位置写字符
void L1602_string(uchar row, uchar column,char *p); //从行列位置写字符串
void L1602_Clear(void); //清屏
void L1602_DispNum(uchar row, uchar column, uint num);
void L1602_DispFloatNum(uchar row, uchar column, double num);
#endif
lcd.c代码:
#include "stm32f10x.h"
#include "lcd_1602.h"
void RCC_Configuration(void);
void Port_Init(void);
int main(void)
{
RCC_Configuration();
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE); //禁用SDJ和JTAG,释放口线用作IO输出
Port_Init();
L1602_init();
while (1)
{
L1602_Clear();
L1602_string(1,1,"Hello, World!");
L1602_string(2,1,"I can do that ");
delay(1000);
L1602_Clear();
L1602_string(1,1,"Integer:");
L1602_DispNum(2,1,100); //显示整数数字
L1602_string(2,5,"V.");
delay(1000);
L1602_Clear();
L1602_string(1,1,"Float:");
L1602_DispFloatNum(2,1,123.898); //显示浮点数
L1602_string(2,8,"V.");
delay(1000);
}
}
void RCC_Configuration(void) //配置系统时钟
{
SystemInit();//72MHz
//下面给各模块开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|
RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//TIM2时钟使能
RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
}
void Port_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //声明GPIO初始化结构变量
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2; // 管脚PB0、1、2
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|
GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|
GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
delay(100);
}
lcd_1602.c:
#include "lcd_1602.h"
#include "stm32f10x_gpio.h"
#include "stdio.h"
#define lcm_ce_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_0) // E-----LCD-Pin6 -----STM32-PB0
#define lcm_ce_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_0)
#define lcm_rst_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_1) // RS----LCD-Pin4-----STM32-PB1
#define lcm_rst_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_1)
#define lcm_wr_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_2) // WR----LCD-Pin5-----STM32-PB2
#define lcm_wr_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_2)
#define DATA_0_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_8) //置0
#define DATA_0_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_8) // 置1
#define DATA_1_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_9)
#define DATA_1_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_9)
#define DATA_2_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_10)
#define DATA_2_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_10)
#define DATA_3_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_11)
#define DATA_3_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_11)
#define DATA_4_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_12)
#define DATA_4_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_12)
#define DATA_5_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_13)
#define DATA_5_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_13)
#define DATA_6_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_14)
#define DATA_6_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_14)
#define DATA_7_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_15)
#define DATA_7_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_15)
void DATA(unsigned int d)
{
if (d&0x01) {DATA_0_HIGH();} else {DATA_0_LOW();}
if (d&0x02) {DATA_1_HIGH();} else {DATA_1_LOW();}
if (d&0x04) {DATA_2_HIGH();} else {DATA_2_LOW();}
if (d&0x08) {DATA_3_HIGH();} else {DATA_3_LOW();}
if (d&0x10) {DATA_4_HIGH();} else {DATA_4_LOW();}
if (d&0x20) {DATA_5_HIGH();} else {DATA_5_LOW();}
if (d&0x40) {DATA_6_HIGH();} else {DATA_6_LOW();}
if (d&0x80) {DATA_7_HIGH();} else {DATA_7_LOW();}
}
void E(unsigned char i) //使能LCD
{
if(i) {lcm_ce_HIGH();} else {lcm_ce_LOW();}
}
void RS(unsigned char i) // 开 RS(0关,!0开)
{
if(i) {lcm_rst_HIGH();} else {lcm_rst_LOW();}
}
void RW(unsigned char i) // 开RW(0关,!0开)
{
if(i) {lcm_wr_HIGH();} else {lcm_wr_LOW();}
}
void delay(uint a)
{
u16 i=0;
while(a--)
{ i=12000;
while(i--) ;
}
}
void delay_us(uint time)
{ u16 i=0;
while(time--)
{ i=10;
while(i--) ;
}
}
void delay_ms(uint time)
{ u16 i=0;
while(time--)
{ i=12000;
while(i--) ;
}
}
void enable(uchar del)
{
DATA(del);
RS(0);
RW(0);
E(0);
delay_ms(10);
E(1);
delay_ms(10);
E(0);
}
void write(uchar del)
{
DATA(del);
RS(1);
RW(0);
E(0);
delay_ms(10);
E(1);
delay_ms(10);
E(0);
}
void L1602_init(void)//1602???,
{
delay_ms(10);
enable(0x38);
delay_ms(10);
enable(0x06);
delay_ms(10);
enable(0x0C);
delay_ms(10);
enable(0x01);
delay_ms(10);
}
void L1602_Clear(void) //1602清屏,
{
delay_ms(10);
enable(0x01);
delay_ms(10);
}
void L1602_char(uchar row, uchar column,char sign)
{
uchar a;
if (row==1) a=0x80;
if (row==2) a=0xc0;
a = a + column - 1;
enable(a);
write(sign);
}
void L1602_string(uchar row, uchar column,char *p)
{
uchar a;
if (row==1) a=0x80;
if (row==2) a=0xc0;
a = a + column - 1;
enable(a);
while(*p!='\0')
{
write(*p);
p++;
}
/*while(1)
{
if (*p==';') break;
write(*p);
p++;
}*/
}
void L1602_DispNum(uchar row, uchar column, uint num)
{
/*
uint i=0,j,k=0,wei,q;
char str[32];
if(num>=10000000)wei=8;
else if(num>=1000000)wei=7;
else if(num>=100000)wei=6;
else if(num>=10000)wei=5;
else if(num>=1000) wei=4;
else if(num>=100)wei=3;
else if(num>=10) wei=2;
else wei=1;
for(i=wei;i>0;i--)
{
q=1;
j=1;
for(;j<i;j++)
{
q *=10; //10*q
}
str[k++]=num/q +'0';
num %= q;
}
str[k] = '\0';
*/
char str[32];
sprintf(str,"%d", num ); // num中存储数据的格式化写入str中
L1602_string(row, column, str); // 在lcd的row行,column列写入str
}
void L1602_DispFloatNum(uchar row, uchar column, double num)
{
char str[32];
sprintf(str,"%.2f", num ); // num中存储的数据格式化写入str中
L1602_string(row, column, str); // 在lcd显示屏的row行,colunm列写str
}
9、LCD结合矩阵键盘输入
lcd_1602.h
/* LCD1602.h*/
#ifndef __LCD1602_H
#define __LCD1602_H
#define uchar unsigned char
#define uint unsigned int
#define uint unsigned int
keyboard.h
int keyscan(void);
void delay_nms(u16 time);
void GPIO_Configuration(void);
keyboard.c
#include "stm32f10x.h"
#define uchar unsigned char
#define uint unsigned int
int keyscan();
void delay_nms(u16 time);
void GPIO_Configuration(void);
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure; // 声明GPIO初始化结构变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 开启PB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 开始PB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 开启复用IO时钟
// ↓ PB3,PB4被用在JTAG接口中,把这两个管脚释放出来,作为普通的IO口
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 |
GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); // PA口初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 |
GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
int keyscan(void)
{
uchar temp;
uchar key;
temp = 0;
GPIO_Write(GPIOA, 0xFFF0); // PB3-PB0 输出低电平
if((GPIOA->IDR & 0x00F0) == 0x00F0) // PB7-PB4全为1,没有按键按下
{
return -1;
}
else
{
delay_nms(5); // 延时去抖
if((GPIOA->IDR & 0x00F0) == 0x00F0) // 抖动产生
{
return -1;
}
}
GPIO_Write(GPIOA, 0xFFFE); // PB3 = PB2 = PB1 = 1?PB0 = 0
temp = ~(GPIOA->IDR | 0xFF0F);
switch(temp) // 对PB7-PB4的值进行判断,
{
case 0x0010 : key = 0; break;
case 0x0020 : key = 1; break;
case 0x0040 : key = 2; break;
case 0x0080 : key = 3; break;
}
GPIO_Write(GPIOA, 0xFFFD); // PB2 = 0,PB0 = PB1 = PB3 = 1
temp = ~(GPIOA->IDR | 0xFF0F);
switch(temp)
{
case 0x0010 : key = 4; break;
case 0x0020 : key = 5; break;
case 0x0040 : key = 6; break;
case 0x0080 : key = 7; break;
}
GPIO_Write(GPIOA, 0xFFFB); // PB3 = PB 1 = PB0 = 1, PB2 = 0
temp = ~(GPIOA->IDR | 0xFF0F);
switch(temp)
{
case 0x0010 : key = 8; break;
case 0x0020 : key = 9; break;
case 0x0040 : key = 10; break;
case 0x0080 : key = 11; break;
}
GPIO_Write(GPIOA, 0xFFF7); // PB3 = 0, PB2 = PB1 = PB0 = 1,
temp = ~(GPIOA->IDR | 0xFF0F);
switch(temp)
{
case 0x0010 : key = 12; break;
case 0x0020 : key = 13; break;
case 0x0040 : key = 14; break;
case 0x0080 : key = 15; break;
}
return key;
}
void delay_nms(u16 time)
{
u16 i = 0;
while(time--)
{
i = 12000;
while(i--);
}
}
lcd_1602.c
#include "lcd_1602.h"
#include "stm32f10x_gpio.h"
#include "stdio.h"
#define lcm_ce_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_0) // E-----LCD-Pin6 -----STM32-PB0
#define lcm_ce_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_0)
#define lcm_rst_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_1) // RS----LCD-Pin4-----STM32-PB1
#define lcm_rst_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_1)
#define lcm_wr_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_2) // WR----LCD-Pin5-----STM32-PB2
#define lcm_wr_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_2)
#define DATA_0_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_8) //复位总线第0位
#define DATA_0_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_8) // 置数据总线第0位
#define DATA_1_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_9)
#define DATA_1_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_9)
#define DATA_2_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_10)
#define DATA_2_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_10)
#define DATA_3_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_11)
#define DATA_3_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_11)
#define DATA_4_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_12)
#define DATA_4_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_12)
#define DATA_5_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_13)
#define DATA_5_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_13)
#define DATA_6_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_14)
#define DATA_6_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_14)
#define DATA_7_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_15)
#define DATA_7_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_15)
void DATA(unsigned int d) // 根据数据d的8位二进制来确定对数据总线上哪一位置位或清零
{
if (d&0x01) {DATA_0_HIGH();} else {DATA_0_LOW();}
if (d&0x02) {DATA_1_HIGH();} else {DATA_1_LOW();}
if (d&0x04) {DATA_2_HIGH();} else {DATA_2_LOW();}
if (d&0x08) {DATA_3_HIGH();} else {DATA_3_LOW();}
if (d&0x10) {DATA_4_HIGH();} else {DATA_4_LOW();}
if (d&0x20) {DATA_5_HIGH();} else {DATA_5_LOW();}
if (d&0x40) {DATA_6_HIGH();} else {DATA_6_LOW();}
if (d&0x80) {DATA_7_HIGH();} else {DATA_7_LOW();}
}
void E(unsigned char i) //使能LCD
{
if(i) {lcm_ce_HIGH();} else {lcm_ce_LOW();}
}
void RS(unsigned char i) // 根据参数i,确定是置位RS,还是清零RS
{
if(i) {lcm_rst_HIGH();} else {lcm_rst_LOW();}
}
void RW(unsigned char i) // 根据参数i,确定是置位RW,还是清零RW
{
if(i) {lcm_wr_HIGH();} else {lcm_wr_LOW();}
}
void delay(uint a)
{
u16 i=0;
while(a--)
{ i=12000;
while(i--) ;
}
}
void delay_us(uint time)
{ u16 i=0;
while(time--)
{ i=10;
while(i--) ;
}
}
void delay_ms(uint time)
{ u16 i=0;
while(time--)
{ i=12000;
while(i--) ;
}
}
void enable(uchar del) // 1602命令函数,输入的命令值,根据时序来使能LCD
{
DATA(del); // 根据命令集,按照时序来使能LCD
RS(0); // RS = 0,选择写指令寄存器, RS = 1 选择写数据寄存器
RW(0); // RW = 0, 进行写操作, RW = 1 进行读操作
E(0); // E 使能位
delay_ms(10);
E(1); // 使能
delay_ms(10);
E(0);
}
void write(uchar del) // 1602写数据函数,输入的是需要写入1602的数据
{
DATA(del);
RS(1);
RW(0);
E(0);
delay_ms(10);
E(1);
delay_ms(10);
E(0);
}
void L1602_init(void) //1602初始化
{
delay_ms(10);
enable(0x38); // 设置16 * 2显示, 5 * 7点阵,8位数据接口
delay_ms(10);
enable(0x06); // 地址+1,当写入数据,光标右移
delay_ms(10);
enable(0x0C); // 开显示,不显示光标
delay_ms(10);
enable(0x01); // 清屏
delay_ms(10);
}
void L1602_Clear(void) //1602清屏,
{
delay_ms(10);
enable(0x01); // 清屏
delay_ms(10);
}
void L1602_char(uchar row, uchar column,char sign) // 按行列位置写字符
{
uchar a;
if (row==1) a=0x80; // 在第一行显示
if (row==2) a=0xc0; // 在第二行显示
a = a + column - 1; // 计算要显示字符的位置
enable(a);
write(sign); // 写字符sign
}
void L1602_string(uchar row, uchar column,char *p) // 从行列位置写字符串
{
uchar a;
if (row==1) a=0x80; // 在第一行显示
if (row==2) a=0xc0; // 在第二行显示
a = a + column - 1; // 计算要显示字符串的位置
enable(a);
while(*p!='\0') // 一直写(没有到末尾)
{
write(*p); // 写进去(字符)
p++;
}
/*while(1)
{
if (*p==';') break;
write(*p);
p++;
}*/
}
void L1602_DispNum(uchar row, uchar column, uint num) // 写入整数
{
char str[32];
sprintf(str,"%d", num ); // 将 num(整数),转化为字符串
L1602_string(row, column, str); // 写
}
void L1602_DispFloatNum(uchar row, uchar column, double num) // 写入浮点数
{
char str[32];
sprintf(str,"%.2f", num ); // 将浮点数转化为字符串(保留两位小数)
L1602_string(row, column, str); // 写
}
lcd.c
#include "stm32f10x.h"
#include "lcd_1602.h"
#include "keyboard.h"
void RCC_Configuration(void);
void Port_Init(void);
int x;
uchar temp;
uchar key;
u16 ReadedData;
int main(void)
{
GPIO_Configuration();
RCC_Configuration();
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);//禁用SDJ和JTAG,释放口线用作IO输出
Port_Init();
L1602_init();
while (1)
{
L1602_Clear();
L1602_string(1,1,"input is Integer!"); //先显示一行,(提示输入)
x = keyscan(); // 获取输入的信息
if(x == -1) // 没有输入就等待
{
while(x == -1)
{
x = keyscan();
}
}
L1602_DispNum(2,1,x); //将得到的x写入
L1602_string(2,5,"xixi");
delay(1000);
L1602_Clear();
}
}
void RCC_Configuration(void) //配置系统时钟
{
SystemInit();//72MHz
//开启各时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//TIM2时钟使能
RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
}
void Port_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//声明GPIO初始化结构体变量
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure); // 初始化管脚
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9|
GPIO_Pin_10|GPIO_Pin_11|
GPIO_Pin_12|GPIO_Pin_13|
GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
delay(100);
}
连线:
10、TFT LCD实验(显示图片)
image2lcd.c
#include "sys.h"
#include "lcd.h"
#include "image2lcd.h"
//从8位数据获得16位颜色
//mode:0,低位在前,高位在后.
// 1,高位在前,低位在后.
//str:数据
u16 image_getcolor(u8 mode,u8 *str)
{
u16 color;
if(mode)
{
color=((u16)*str++)<<8;
color|=*str;
}else
{
color=*str++;
color|=((u16)*str)<<8;
}
return color;
}
//在液晶上画图
//xsta,ysta,xend,yend:画图区域
//scan:见image2lcd V2.9的说明.
//*p:图像数据
void image_show(u16 xsta,u16 ysta,u16 xend,u16 yend,u8 scan,u8 *p)
{
u32 i;
u32 len=0;
LCD_Set_Window(xsta,ysta,xend,yend);
if((scan&0x03)==0)//水平扫描
{
switch(scan>>6)//设置扫描方式
{
case 0:
LCD_Scan_Dir(L2R_U2D);//从左到右,从上到下
LCD_SetCursor(xsta,ysta);//设置光标位置
break;
case 1:
LCD_Scan_Dir(L2R_D2U);//从左到右,从下到上
LCD_SetCursor(xsta,yend);//设置光标位置
break;
case 2:
LCD_Scan_Dir(R2L_U2D);//从右到左,从上到下
LCD_SetCursor(xend,ysta);//设置光标位置
break;
case 3:
LCD_Scan_Dir(R2L_D2U);//从右到左,从下到上
LCD_SetCursor(xend,yend);//设置光标位置
break;
}
}else //垂直扫描
{
switch(scan>>6)//设置扫描方式
{
case 0:
LCD_Scan_Dir(U2D_L2R);//从上到下,从左到右
LCD_SetCursor(xsta,ysta);//设置光标位置
break;
case 1:
LCD_Scan_Dir(D2U_L2R);//从下到上从,左到右
LCD_SetCursor(xsta,yend);//设置光标位置
break;
case 2:
LCD_Scan_Dir(U2D_R2L);//从上到下,从右到左
LCD_SetCursor(xend,ysta);//设置光标位置
break;
case 3:
LCD_Scan_Dir(D2U_R2L);//从下到上,从右到左
LCD_SetCursor(xend,yend);//设置光标位置
break;
}
}
LCD_WriteRAM_Prepare(); //开始写入GRAM
len=(xend-xsta+1)*(yend-ysta+1); //写入的数据长度
for(i=0;i<len;i++)
{
LCD_WR_DATA(image_getcolor(scan&(1<<4),p));
p+=2;
}
#if USE_HORIZONTAL //使用横屏
LCD_Set_Window(0,0,319,239);
#else
LCD_Set_Window(0,0,239,319);
#endif
}
//在指定的位置显示一个图片
//此函数可以显示image2lcd软件生成的任意16位真彩色图片.
//限制:1,尺寸不能超过屏幕的区域.
// 2,生成数据时不能勾选:高位在前(MSB First)
// 3,必须包含图片信息头数据
//x,y:指定位置
//imgx:图片数据(必须包含图片信息头,"4096色/16位真彩色/18位真彩色/24位真彩色/32位真彩色”的图像数据头)
//注意:针对STM32,不能选择image2lcd的"高位在前(MSB First)"选项,否则imginfo的数据将不正确!!
void image_display(u16 x,u16 y,u8 * imgx)
{
HEADCOLOR *imginfo;
u8 ifosize=sizeof(HEADCOLOR);//得到HEADCOLOR结构体的大小
imginfo=(HEADCOLOR*)imgx;
image_show(x,y,x+imginfo->w-1,y+imginfo->h-1,imginfo->scan,imgx+ifosize);
}
main.c
#include "stm32f10x.h"
#include "delay.h"
#include "image2lcd.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "led.h"
extern const u8 gImage_zz[];//图片数据(包含信息头),存储在image1.c里面. 需要用Image2Lcd去处理成c语言模式
int main(void)
{
delay_init(); //延时函数初始化
uart_init(9600); //串口初始化为9600
LED_Init(); //初始化与LED连接的硬件接口
LCD_Init();
HEADCOLOR *imginfo;
u16 x=0,y=0;
imginfo=(HEADCOLOR*)gImage_zz; //得到文件信息
POINT_COLOR=RED;
delay_ms(1500);//等待1.5秒
srand(imginfo->h*imginfo->w);
while(1)
{
image_display(x,y,(u8*)gImage_zz);//在指定地址显示图片
LCD_ShowString(130,280,240,12,12,"By QLU_fuchen");
delay_ms(200);
}
}
对于剩下的代码嘛,导入来导入去的,去正点原子的资料里面找吧 (The code comes from 原子哥)
11、中断(把代码贴贴,以后粘贴过去修改)
#include "stm32f10x.h"
char flag = 0;
void RCC_Configuration(void);
void GPIO_Configuration(void);
void EXTI_Configuration(void);
void NVIC_Configuration(void);
void delay_nms(u16 time);
int main(void)
{
RCC_Configuration(); // 时钟
GPIO_Configuration(); // GPIO
EXTI_Configuration(); // 外部中断
NVIC_Configuration(); // 向量中断控制器
while(1)
{
if (flag)
{
GPIO_SetBits(GPIOA,GPIO_Pin_8);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
delay_nms(500);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
delay_nms(500);
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
delay_nms(500);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
delay_nms(500);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
delay_nms(500);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
delay_nms(500);
}else{
GPIO_SetBits(GPIOA,GPIO_Pin_8);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
delay_nms(500);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
delay_nms(500);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
delay_nms(500);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
delay_nms(500);
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
delay_nms(500);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
delay_nms(500);
}
}
}
void RCC_Configuration(void) // 配置时钟
{
SystemInit(); //72MHz
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 使能AFIO时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //关掉JTAG,不关SW
// STM32中PA13、PA14、PA15、PB03PB04是默认的FTAG引脚映射
// 释放PA15 (PA15默认为JTAG功能,这里为了使用PA15需要首先释放口线)
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU ;
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
}
void EXTI_Configuration(void) // 配置外部中断源
{
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line15|EXTI_Line5; // 外部中短线Line12 | Line5
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; //选择中断模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStructure.EXTI_LineCmd=ENABLE; //使能中断
EXTI_Init(&EXTI_InitStructure); // 初始化外部中断
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15); //PA15配置为外部中断源(本质利用AFIO_EXTICR寄存器)
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5); //PC5配置为外部中断源(本质利用AFIO_EXTICR寄存器)
}
void NVIC_Configuration(void) // 嵌套向量中断初始化
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 中断优先级分组
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; // EXTI9_5中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //占先优先级设定,取值为0-1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级设定、取值0-7
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn; //EXTI9_5中断源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占先优先设计定,取值为0-1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级设计定,取值为0-7
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI9_5_IRQHandler(void) // 外部中断源9_5中断子程序
{
if(EXTI_GetITStatus(EXTI_Line5) != RESET)
{
flag=1;
EXTI_ClearFlag(EXTI_Line5);
}
}
void EXTI15_10_IRQHandler(void) // 外部中断源15_10中断子程序
{
if (EXTI_GetITStatus(EXTI_Line15)!=RESET)
{
flag=0;
EXTI_ClearFlag(EXTI_Line15);
}
}
void delay_nms(u16 time) //延时
{
u16 i=0;
while(time--)
{
i = 4000;
while(i--);
}
}
12、USART(串口通信)
/*
基本的USART代码
通过USART1发送数据、PC机上运行串口调试助手软件接收字符
如果串口没有显示正确的输出,检查Target/Code Generation中的Use MicroLIB项是否被选中
*/
#include "stm32f10x.h"
#include <stdio.h>
#include <string.h>
#define RxBufferSize 10
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
void NVIC_Configuration(void);
int fputc(int ch, FILE *f);/*重定向,修改一下选中Use MicroLIB ,
需要在 Target/Code Generation??Use MicroLIB
才能使用printf */
void delay_nms(u16 time);//延时子程序
unsigned char RxBuffer[RxBufferSize];
unsigned char CmdBuffer[RxBufferSize];
unsigned char Rx_Flag = 0;
unsigned char RxCounter=0;
u16 i;
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
USART_Configuration();
NVIC_Configuration();
USART_ClearFlag(USART1,USART_FLAG_TC);// 清发送结束位
USART_SendData(USART1, 'A'); // 向发送数据寄存器写一个字节
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
USART_SendData(USART1,'B');
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
printf("\r\n");
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
printf("zzzz\n");
printf("打开LED灯,请输入 ON!\n");
printf("关闭LED灯,请输入 OFF!\n");
printf("输入错误的话,LED闪烁10次!\n");
GPIO_SetBits(GPIOA,GPIO_Pin_8);//PA8置位,LED1灯灭
memset(CmdBuffer,10,0);
while(1)
{
if (Rx_Flag == 1)
{
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); //关闭接收中断
Rx_Flag = 0;
RxCounter=0;
if(strstr(CmdBuffer,"OFF"))
{
GPIO_SetBits(GPIOA,GPIO_Pin_8);//PA8置位,LED1灯灭
memset(CmdBuffer,10,0);
}
else if(strstr(CmdBuffer,"ON"))
{
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
memset(CmdBuffer,10,0);
}
else
{
memset(CmdBuffer,10,0);
for (i=0;i<10;i++)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_8);//PA8清零,LED1灯亮
delay_nms(200);
GPIO_SetBits(GPIOA,GPIO_Pin_8);//PA8置位,LED1灯灭
delay_nms(200);
}
}
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断,接收寄存器不空(RXNE = 1)时产生中断
}
}
}
void RCC_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1的时钟
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//声明GPIO初始化结构变量
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //配置管脚PA10/USART1_RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA10
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //配置管脚PA9/USART1_TX
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //IO配置为复用输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8; //配置管脚8
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //IO口配置为推挽输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //工作频率50MHz
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA8口
}
void NVIC_Configuration(void) //NVIC配置
{
//配置NVIC的优先级
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //优先级分组1(0:4, 0位抢占优先级、4位子优先级?
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //设置串口1 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级位0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 串口中断使能
NVIC_Init(&NVIC_InitStructure);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //USART_WordLength_8b; //8 数据 //USART_WordLength_9b; //9 位数据
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//USART_StopBits_1 ;//在帧结尾传输1个停止位
//USART_StopBits_0.5;//在帧结尾传输0.5个停止位
//USART_StopBits_2 ;//在帧结尾传输2个停止位
//USART_StopBits_1.5;//在帧结尾传输1.5个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;
//USART_Parity_No ;//奇偶失能
//USART_Parity_Even;//偶模式
//USART_Parity_Odd ;//奇模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//USART_HardwareFlowControl_None; //硬件流控制失能
//USART_HardwareFlowControl_RTS; //发送请求 RTS使能
//USART_HardwareFlowControl_CTS; //清除请求 CTS使能
//USART_HardwareFlowControl_RTS_CTS;//RTS和 CTS使能
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
//USART_Mode_Tx;//发送使能
//USART_Mode_Rx;//接收使能
USART_Init(USART1, &USART_InitStructure);//初始化串口
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断,接收寄存器不空(RXNE=1)时产生中断
//USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 开启发送中断,发送寄存器空(TXE=1)时使能产生中断
/*串口的发送中断有两个,分别是:
l、发送数据寄存器空中断(TXE)
2、发送完成中断(TC)*/
USART_Cmd(USART1, ENABLE); //启动USART
}
int fputc(int ch,FILE *f)
{
if(ch=='\n')
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
USART_SendData(USART1,'\r');
}
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET)
;
USART_SendData(USART1,ch);
return ch;
}
void delay_nms(u16 time)//延时子程序
{
u16 i=0;
while(time--)
{
i=12000;
while(i--) ;
}
}
void USART1_IRQHandler(void) //串口1 中断服务程序
{
unsigned int i=0;
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判断接收寄存器是否为空
{
//如果接收寄存器非空,说明检测到中断读入
RxBuffer[RxCounter++] = USART_ReceiveData(USART1); // Read one byte from the receive data register
if (RxBuffer[RxCounter-1]=='\n') //如果检测到换行,则设置接收标志位为1
// \n:换行,光标到下行行首
// \r:回车,光标到本行行首
{
Rx_Flag=1;
for (i=0;i<RxCounter;i++)//把接收的数据缓存到CmdBuffer中
{
CmdBuffer[i]=RxBuffer[i];
}
CmdBuffer[RxCounter]=0; //发送缓冲区结束符
RxCounter=0;
}
if(RxCounter == RxBufferSize) //如菇邮整缓冲区满了
{
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); //关闭接收中断
Rx_Flag=1;
CmdBuffer[RxCounter]=0; //接收命令缓冲区结束符
RxCounter=0;
}
}
}
USART转发
/*
PA9->USARTI_TX
PA10->USART1_RX
利用USART的中断进行接收和发送数据
用到了串口助手
ps:注意晶振的频率
*/
#include "stm32f10x.h"
#include <stdio.h>
#include <string.h>
#define TxBufferSize (countof(TxBuffer) - 1) //定义UART1的发送缓冲器的字节数
#define RxBufferSize 0x51 //定义USART1的接收缓冲器的字节数
#define countof(a) (sizeof(a) / sizeof(*(a)))
u8 TxBuffer[] = "Stm32.USART->Computer. Developed by Ph.D. A. Dong, Qilu Univerity of Technology.\r\n" ;
u8 RxBuffer[RxBufferSize];
u8 NbrOfDataToTransfer = TxBufferSize;
u8 NbrOfDataToRead = RxBufferSize;
u8 TxCounter = 0;
u16 RxCounter = 0;
u8 Tx_Flag=0;
u8 Rx_Flag=0;
void RCC_Configuration(void); //时钟配置
void GPIO_Configuration(void); //GOPO配置
void USART_Configuration(void);//USART配置
void NVIC_Configuration(void);//NVIC配置
void delay_nms(u16 time);//延时子程序
unsigned int i;
int main(void)
{
RCC_Configuration(); //配置时钟
NVIC_Configuration();//配置NVIC
GPIO_Configuration(); //配置GPIO
USART_Configuration();//配置USART
while(1)
{
USART_ClearFlag(USART1,USART_FLAG_TC);//清发送结束位
USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 开启发送
delay_nms(2000);
if(Rx_Flag==1) //如果接收到的一组以换行结束的数据,则将接收到的数据在发送出去
{
//判断是否接收到一帧有效数据
Rx_Flag=0;
for(i=0; i< NbrOfDataToRead; i++) TxBuffer[i] = 0;
// TxBuffer[0]='\n';
// TxBuffer[1]='\r';
for(i=0; i< RxCounter; i++) TxBuffer[i] = RxBuffer[i];
//TxBuffer[RxCounter]='\r';
//TxBuffer[RxCounter+1]='\n';
//TxBuffer[RxCounter+2]='\r';
//将接收缓冲器的数据转到发送缓冲区,并在缓冲区头上加上换行符,准备转发
RxCounter=0;
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断,接收寄存器不空(RXNE=1)时产生中断
USART_ITConfig(USART1, USART_IT_TXE, ENABLE); //开启发送中断
delay_nms(2000);
}
}
}
void RCC_Configuration(void) // 时钟配置子程序
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1的时钟, USART1挂接到APB2上。其他USART2-5挂接到APB!上
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 使能AFIO的时钟,串口属于复用功能
}
void GPIO_Configuration(void) // GPIO配置
{
GPIO_InitTypeDef GPIO_InitStructure;//声明GPIO初始化结构变量
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //配置管脚PA10/USART1_RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA10
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //配置管脚PA9/USART1_TX
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //IO配置为复用输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9
}
void NVIC_Configuration(void) //NVIC配置
{
//配置NVIC相应的优先级位
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //优先级分组1(1:3,1位抢占优先级、3位子优先级)
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //设置串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 子优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 串口中断使能
NVIC_Init(&NVIC_InitStructure);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //USART_WordLength_8b; //8 数据 //USART_WordLength_9b; //9 位数据
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//USART_StopBits_1 ;//在帧结尾传输1个停止位
//USART_StopBits_0.5;//在帧结尾传输0.5个停止位
//USART_StopBits_2 ;//在帧结尾传输2个停止位
//USART_StopBits_1.5;//在帧结尾传输1.5个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;
//USART_Parity_No ;//奇偶失能
//USART_Parity_Even;//偶模式
//USART_Parity_Odd ;//奇模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//USART_HardwareFlowControl_None; //硬件流控制失能
//USART_HardwareFlowControl_RTS; //发送请求 RTS使能
//USART_HardwareFlowControl_CTS; //清除请求 CTS使能
//USART_HardwareFlowControl_RTS_CTS;//RTS和 CTS使能
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
//USART_Mode_Tx;//发送使能
//USART_Mode_Rx;//接收使能
USART_Init(USART1, &USART_InitStructure);//初始化串口
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断,接收寄存器不空(RXNE=1)时产生中断
USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 开启发送中断,发送寄存器空(TXE=1)时使能产生中断
/*串口的发送中断有两个,分别是:
l、发送数据寄存器空中断(TXE)
2、发送完成中断(TC)*/
USART_Cmd(USART1, ENABLE); //启动USART
}
void delay_nms(u16 time)//延时子程序
{
u16 i=0;
while(time--)
{
i=12000;
while(i--) ;
}
}
void USART1_IRQHandler(void) //串口1 中断服务程序
{
unsigned int i=0;
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判断接收寄存器是否非空
{
//当检测到中断读入
RxBuffer[RxCounter++] = USART_ReceiveData(USART1); // Read one byte from the receive data register
if (RxBuffer[RxCounter-1]=='\n') //如果检测到换行,则设置接收标志位1
// \n:换行,光标到下行行首
// \r:回车,光标到本行行首
{
Rx_Flag=1;
TxBuffer[RxCounter]=0; //发送缓冲区结束符
}
if(RxCounter == NbrOfDataToRead) //如果接收缓冲区满了
{
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); //关闭接收中断
Rx_Flag=1;
TxBuffer[RxCounter]=0; //发送缓冲区结束符
}
}
if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
{
//当检测到发送中断
USART_SendData(USART1, TxBuffer[TxCounter++]); //向发送数据寄存器写一个字节
if(TxCounter == NbrOfDataToTransfer)
{
TxCounter=0;
USART_ITConfig(USART1, USART_IT_TXE, DISABLE); /* Disable the USART1 Transmit interrupt */
}
}
}
13、DMA实例
(1)存储器至存储器传输
#include "stm32f10x.h"
#include <stdio.h>
void RCC_Configuration(void);
void GPIO_Configuration(void);
void DMA_Configuration(void);
void USART_Configuration(void);
int fputc(int ch, FILE *f);//重定向
void delay_nms(u16 time);
uint8_t SrcBuf[10]="Hello DMA";
uint8_t DstBuf[10]="DMA Hello";
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
USART_Configuration();
DMA_Configuration();
USART_ClearFlag(USART1,USART_FLAG_TC);//清发送结束位
// USART_SendData(USART1, 'A'); //向发送数据寄存器写一个字节
// while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
// USART_SendData(USART1,'B');
printf("Before the DMA transfer:\n");
printf("DstBuf: %s\n",DstBuf);
DMA_Cmd(DMA1_Channel1,ENABLE);
printf("After the DMA transfer:\n");
printf("DstBuf: %s\n",DstBuf);
while(1)
{
GPIO_SetBits(GPIOA,GPIO_Pin_8);
delay_nms(200);
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
delay_nms(200);
}
}
void RCC_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1的时钟, USART1挂接到APB2上
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//声明GPIO初始化结构变量
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //配置管脚PA10/USART1_RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA10
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //配置管脚PA9/USART1_TX
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //IO配置为复用输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8; //配置管脚8
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //IO口配置为复用输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //工作频率50MHz
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA8口
}
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* DMA channel1 configuration */
DMA_DeInit(DMA1_Channel1);//重置DMA的寄存器的值,配置为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)SrcBuf;/*设置DMA外设基地址,即源数据存储区的首地址*/
DMA_InitStructure.DMA_MemoryBaseAddr =(u32)DstBuf;/*定义内存基地址*/
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;/*设置数据传输方向,从外设读取数据*/
// DMA_DIR_PeripheralSRC // 两种传输方向的设置
// DMA_DIR_PeripheralDST
DMA_InitStructure.DMA_BufferSize = 10;/*指定DMA通道,DMA缓存的大小*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;/*设置外设数据指针调整模数,地址指针自动增加*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /*设置内存地址递增*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;/* 定义外设和内存的数据宽度 */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;/* 设定DMA工作正常模式,即按照指定的缓存大传输,不在进行循环 */
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable; // 开启存储器到存储器模式
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //USART_WordLength_8b; //8 数据 //USART_WordLength_9b; //9 位数据
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//USART_StopBits_1 ;//在帧结尾传输1个停止位
//USART_StopBits_0.5;//在帧结尾传输0.5个停止位
//USART_StopBits_2 ;//在帧结尾传输2个停止位
//USART_StopBits_1.5;//在帧结尾传输1.5个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;
//USART_Parity_No ;//奇偶失能
//USART_Parity_Even;//偶模式
//USART_Parity_Odd ;//奇模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//USART_HardwareFlowControl_None; //硬件流控制失能
//USART_HardwareFlowControl_RTS; //发送请求 RTS使能
//USART_HardwareFlowControl_CTS; //清除请求 CTS使能
//USART_HardwareFlowControl_RTS_CTS;//RTS和 CTS使能
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
//USART_Mode_Tx;//发送使能
//USART_Mode_Rx;//接收使能
USART_Init(USART1, &USART_InitStructure);//初始化串口
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断,接收寄存器不空(RXNE=1)时产生中断
//USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 开启发送中断,发送寄存器空(TXE=1)时使能产生中断
/*串口的发送中断有两个,分别是:
l、发送数据寄存器空中断(TXE)
2、发送完成中断(TC)*/
USART_Cmd(USART1, ENABLE); //启动USART
}
int fputc(int ch,FILE *f)
{
if(ch=='\n')
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
USART_SendData(USART1,'\r');
}
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET)
;
USART_SendData(USART1,ch);
return ch;
}
void delay_nms(u16 time)//延时子程序
{
u16 i=0;
while(time--)
{
i=12000;
while(i--) ;
}
}
(2)DMA存储器到外设传输
使用前再main方法里面调用代码
USART_ClearFlag(USART1,USART_FLAG_TC);//清发送结束位
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
DMA_Cmd(DMA1_Channel4, ENABLE);
DMA的配置:
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* DMA channel1 configuration */
DMA_DeInit(DMA1_Channel4);//重置DMA的寄存器的值,配置为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&USART1->DR;/*设置DMA外设基地址,即源数据存储区的首地址*/
DMA_InitStructure.DMA_MemoryBaseAddr =(u32)SrcBuf;/*定义内存基地址*/
// DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;/*设置数据传输方向,从外设读取数据*/
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
// DMA_DIR_PeripheralSRC // 两种传输方向的设置
// DMA_DIR_PeripheralDST
DMA_InitStructure.DMA_BufferSize = 11;/*指定DMA通道,DMA缓存的大小*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;/*设置外设数据指针调整模数,地址指针自动增加*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /*设置内存地址递增*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;/* 定义外设和内存的数据宽度 */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;/* 设定DMA工作正常模式,即按照指定的缓存大传输,不在进行循环 */
DMA_InitStructure.DMA_Priority = DMA_Priority_High;/*设定DMA选定的通道的软件优先级*/
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;// 开启存储器到存储器模式
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
}
其他的同(1)代码
(3)DMA外设到存储器传输
#include "stm32f10x.h"
#include <stdio.h>
#include <string.h>
void RCC_Configuration(void);
void GPIO_Configuration(void);
void DMA_Configuration(void);
void USART_Configuration(void);
int fputc(int ch, FILE *f);
void delay_nms(u16 time);//?????
char SrcBuf[12]="xxxxxxxxxxx";
int main(void)
{
char flag = 1;
RCC_Configuration();
GPIO_Configuration();
USART_Configuration();
DMA_Configuration();
USART_ClearFlag(USART1,USART_FLAG_TC);//清发送位
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);//允许USART接收DMA请求
DMA_Cmd(DMA1_Channel5, ENABLE); // 启动DMA
while(flag)
{
if(strstr(SrcBuf, "LED"))
{
printf(SrcBuf);
flag = 0;
}
}
while(1)
{
GPIO_SetBits(GPIOA,GPIO_Pin_8);
delay_nms(200);
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
delay_nms(200);
}
}
void RCC_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1的时钟, USART1挂接到APB2上
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//声明GPIO初始化结构变量
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //配置管脚PA10/USART1_RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA10
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //配置管脚PA9/USART1_TX
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //IO配置为复用输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8; //配置管脚8
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //IO口配置为复用输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //工作频率50MHz
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA8口
}
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* DMA channel1 configuration */
DMA_DeInit(DMA1_Channel5);//重置DMA的寄存器的值,配置为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&USART1->DR;/*设置DMA外设基地址,即源数据存储区的首地址*/
DMA_InitStructure.DMA_MemoryBaseAddr =(u32)SrcBuf;/*定义内存基地址*/
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;/*设置数据传输方向为从内存到外设*/
// DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 11;/*指定DMA通道,DMA缓存的大小*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;/*外设地址不变*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /*内存地址递增*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;/*定义外设和内存的数据宽度*/
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;/*设定DMA工作正常模式,即按照指定的缓存大小传输,不在进行循环*/
// DMA_Mode_Circular 循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;/*设定DMA选定的通道的软件的优先级*/
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//关闭存储器到存储器模式
DMA_Init(DMA1_Channel5, &DMA_InitStructure); // 初始化DMA1_Channel5
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //USART_WordLength_8b; //8 数据 //USART_WordLength_9b; //9 位数据
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//USART_StopBits_1 ;//在帧结尾传输1个停止位
//USART_StopBits_0.5;//在帧结尾传输0.5个停止位
//USART_StopBits_2 ;//在帧结尾传输2个停止位
//USART_StopBits_1.5;//在帧结尾传输1.5个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;
//USART_Parity_No ;//奇偶失能
//USART_Parity_Even;//偶模式
//USART_Parity_Odd ;//奇模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//USART_HardwareFlowControl_None; //硬件流控制失能
//USART_HardwareFlowControl_RTS; //发送请求 RTS使能
//USART_HardwareFlowControl_CTS; //清除请求 CTS使能
//USART_HardwareFlowControl_RTS_CTS;//RTS和 CTS使能
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
//USART_Mode_Tx;//发送使能
//USART_Mode_Rx;//接收使能
USART_Init(USART1, &USART_InitStructure);//初始化串口
//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断,接收寄存器不空(RXNE=1)时产生中断
//USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 开启发送中断,发送寄存器空(TXE=1)时使能产生中断
/*串口的发送中断有两个,分别是:
l、发送数据寄存器空中断(TXE)
2、发送完成中断(TC)*/
USART_Cmd(USART1, ENABLE); //启动USART
}
int fputc(int ch,FILE *f)
{
if(ch=='\n')
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
USART_SendData(USART1,'\r');
}
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET)
;
USART_SendData(USART1,ch);
return ch;
}
void delay_nms(u16 time)//延时子程序
{
u16 i=0;
while(time--)
{
i=12000;
while(i--) ;
}
}
14、ADC,DAC
利用ADC,获得内部电压,和温度
#include "stm32f10x.h"
#include <stdio.h>
#include <string.h>
#define ADC_CH_TEMP ADC_Channel_16 //温度传感器通道
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
void NVIC_Configuration(void);
//电压的
u16 Get_Adc(u8 ch);
u16 Get_Adc_Average(u8 ch,u8 times);
void Adc_Init(void);
//温度的
void T_Adc_Init(void);
u16 T_Get_Adc(u8 ch);
u16 T_Get_Temp(void);
u16 T_Get_Adc_Average(u8 ch,u8 times);
u16 adcx;
float temp;
float temperate;
int fputc(int ch, FILE *f);//输出重定向
void delay_nms(u16 time);
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
USART_Configuration();
NVIC_Configuration();
Adc_Init(); // 电压的
T_Adc_Init();// 温度的
while(1)
{
adcx = Get_Adc_Average(ADC_Channel_1,10);
temp = (float)adcx*(3.3/4096);
printf("ADC的值为:%d, 转化为电压是:%lfV, QLU_fuchen \n", adcx, temp);
adcx = T_Get_Adc_Average(ADC_CH_TEMP, 10);
temp = (float)adcx * (3.3 / 4096);
temperate = temp;
temperate = (1.43 - temperate) / 0.0043 + 25;
printf("ADC的值为:%d, 转化为温度是:%lf℃, QLU_fuchen \n", adcx, temperate);
printf("\n");
delay_nms(2000);
}
}
void RCC_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1的时钟
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//声明GPIO初始化结构变量
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //配置管脚PA10/USART1_RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA10
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //配置管脚PA9/USART1_TX
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //IO配置为复用输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8; //配置管脚8
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //IO口配置为推挽输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //工作频率50MHz
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA8口
}
void NVIC_Configuration(void) //NVIC配置
{
//配置NVIC的优先级
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //优先级分组1(0:4, 0位抢占优先级、4位子优先级?
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //设置串口1 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级位0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 串口中断使能
NVIC_Init(&NVIC_InitStructure);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //USART_WordLength_8b; //8 数据 //USART_WordLength_9b; //9 位数据
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//USART_StopBits_1 ;//在帧结尾传输1个停止位
//USART_StopBits_0.5;//在帧结尾传输0.5个停止位
//USART_StopBits_2 ;//在帧结尾传输2个停止位
//USART_StopBits_1.5;//在帧结尾传输1.5个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;
//USART_Parity_No ;//奇偶失能
//USART_Parity_Even;//偶模式
//USART_Parity_Odd ;//奇模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//USART_HardwareFlowControl_None; //硬件流控制失能
//USART_HardwareFlowControl_RTS; //发送请求 RTS使能
//USART_HardwareFlowControl_CTS; //清除请求 CTS使能
//USART_HardwareFlowControl_RTS_CTS;//RTS和 CTS使能
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
//USART_Mode_Tx;//发送使能
//USART_Mode_Rx;//接收使能
USART_Init(USART1, &USART_InitStructure);//初始化串口
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断,接收寄存器不空(RXNE=1)时产生中断
//USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 开启发送中断,发送寄存器空(TXE=1)时使能产生中断
/*串口的发送中断有两个,分别是:
l、发送数据寄存器空中断(TXE)
2、发送完成中断(TC)*/
USART_Cmd(USART1, ENABLE); //启动USART
}
int fputc(int ch,FILE *f)
{
if(ch=='\n')
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
USART_SendData(USART1,'\r');
}
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET)
;
USART_SendData(USART1,ch);
return ch;
}
void delay_nms(u16 time)//?????
{
u16 i=0;
while(time--)
{
i=12000;
while(i--) ;
}
}
//下面是电压的代码
void Adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA1 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
}
u16 Get_Adc(u8 ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);
delay_nms(5);
}
return temp_val/times;
}
// 下面的温度的代码
//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3
void T_Adc_Init(void) //ADC通道初始化
{
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE ); //使能GPIOA,ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //分频因子6时钟为72M/6=12MHz
ADC_DeInit(ADC1); //将外设 ADC1 的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_TempSensorVrefintCmd(ENABLE); //开启内部温度传感器
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //重置指定的ADC1的复位寄存器
while(ADC_GetResetCalibrationStatus(ADC1)); //获取ADC1重置校准寄存器的状态,设置状态则等待
ADC_StartCalibration(ADC1); //
while(ADC_GetCalibrationStatus(ADC1)); //获取指定ADC1的校准程序,设置状态则等待
}
u16 T_Get_Adc(u8 ch)
{
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道3,第一个转换,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
//得到ADC采样内部温度传感器的值
//取10次,然后平均
u16 T_Get_Temp(void)
{
u16 temp_val=0;
u8 t;
for(t=0;t<10;t++)
{
temp_val+=T_Get_Adc(ADC_Channel_16); //TampSensor
delay_nms(5);
}
return temp_val/10;
}
//获取通道ch的转换值
//取times次,然后平均
u16 T_Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=T_Get_Adc(ch);
delay_nms(5);
}
return temp_val/times;
}
![](https://i-blog.csdnimg.cn/blog_migrate/a9ace157beeb3347209971234db0d053.png)
获取DAC通道中存储的数值,并转化为相应的电压通过串口显示
#include "stm32f10x.h"
#include <stdio.h>
#include <string.h>
void Dac1_Init(void); //DAC通道1初始化
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
void EXTI_Configuration(void);
void NVIC_Configuration(void);
int fputc(int ch, FILE *f);// 输出重定向
void delay_ms(u16 time);
void Adc_Init(void); // ADC的初始化
void Dac1_Init(void); //DAC通道1的初始化
u16 Get_Adc(u8 ch); // 获取 ADC通道值
u16 Get_Adc_Average(u8 ch,u8 times); // 获取一段时间内通道的平均值
u16 adcx;
float temp;
char flag = 0;
u16 dacval = 1000;
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
USART_Configuration();
EXTI_Configuration(); // 配置外部中断源
NVIC_Configuration(); // 嵌套向量中断初始化
Adc_Init(); //ADC初始化
Dac1_Init(); //DAC通道1初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
u8 t = 0;
DAC_SetChannel1Data(DAC_Align_12b_R, dacval);
while(1)
{
while(1)
{
t++;
if(t == 2) //两次刷新一次
{
adcx=DAC_GetDataOutputValue(DAC_Channel_1); //获取DAC通道存储的数值
printf("DAC VAL: %d.\n", adcx);
temp=(float)adcx*(3.3/4096); //得到DAC电压值
printf("DAC VOL: %lfV\n", temp);
adcx=Get_Adc_Average(ADC_Channel_1,10); //得到ADC转换值
temp=(float)adcx*(3.3/4096); //得到ADC电压值
printf("ADC VOL:%lfV\n", temp);
t=0;
printf("\n\n");
}
delay_ms(1000);
}
}
}
void RCC_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能AFIO时钟(开始管脚的复用功能)
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //关掉JTAG,不关SW
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//声明GPIO初始化结构变量
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //配置管脚PA10/USART1_RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //配置管脚PA9/USART1_TX
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //IO配置为复用输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //IO口配置为推挽输出口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU ;
GPIO_Init(GPIOC,&GPIO_InitStructure);
}
void EXTI_Configuration(void) // 配置外部中断源
{
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line15|EXTI_Line5; // 外部中短线Line12 | Line5
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; //选择中断模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStructure.EXTI_LineCmd=ENABLE; //使能中断
EXTI_Init(&EXTI_InitStructure); // 初始化外部中断
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15); //PA15配置为外部中断源(本质利用AFIO_EXTICR寄存器)
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5); //PC5配置为外部中断源(本质利用AFIO_EXTICR寄存器)
}
void NVIC_Configuration(void) // 嵌套向量中断初始化
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 中断优先级分组
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; // EXTI9_5中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //占先优先级设定,取值为0-1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级设定、取值0-7
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn; //EXTI9_5中断源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //占先优先设计定,取值为0-1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级设计定,取值为0-7
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI9_5_IRQHandler(void) // 外部中断源9_5中断子程序
{
if(EXTI_GetITStatus(EXTI_Line5) != RESET)
{
if(dacval < 4000){
dacval += 200;
}
DAC_SetChannel1Data(DAC_Align_12b_R, dacval);
EXTI_ClearFlag(EXTI_Line5);
}
}
void EXTI15_10_IRQHandler(void) // 外部中断源15_10中断子程序
{
if (EXTI_GetITStatus(EXTI_Line15)!=RESET)
{
if(dacval>200)dacval -= 200;
else dacval=0;
DAC_SetChannel1Data(DAC_Align_12b_R, dacval);
EXTI_ClearFlag(EXTI_Line15);
}
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //USART_WordLength_8b; //8 数据 //USART_WordLength_9b; //9 位数据
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//USART_StopBits_1 ;//在帧结尾传输1个停止位
//USART_StopBits_0.5;//在帧结尾传输0.5个停止位
//USART_StopBits_2 ;//在帧结尾传输2个停止位
//USART_StopBits_1.5;//在帧结尾传输1.5个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;
//USART_Parity_No ;//奇偶失能
//USART_Parity_Even;//偶模式
//USART_Parity_Odd ;//奇模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//USART_HardwareFlowControl_None; //硬件流控制失能
//USART_HardwareFlowControl_RTS; //发送请求 RTS使能
//USART_HardwareFlowControl_CTS; //清除请求 CTS使能
//USART_HardwareFlowControl_RTS_CTS;//RTS和 CTS使能
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
//USART_Mode_Tx;//发送使能
//USART_Mode_Rx;//接收使能
USART_Init(USART1, &USART_InitStructure);//初始化串口
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断,接收寄存器不空(RXNE=1)时产生中断
//USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 开启发送中断,发送寄存器空(TXE=1)时使能产生中断
/*串口的发送中断有两个,分别是:
l、发送数据寄存器空中断(TXE)
2、发送完成中断(TC)*/
USART_Cmd(USART1, ENABLE); //启动USART
}
int fputc(int ch,FILE *f)
{
if(ch=='\n')
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
USART_SendData(USART1,'\r');
}
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET)
;
USART_SendData(USART1,ch);
return ch;
}
void delay_ms(u16 time)
{
u16 i=0;
while(time--)
{
i=12000;
while(i--) ;
}
}
//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3
void Adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA1 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
}
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);
delay_ms(5);
}
return temp_val/times;
}
//DAC通道1输出初始化
void Dac1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能PORTA通道时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4) ;//PA.4 输出高
DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能 TEN1=0
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化DAC通道1
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
}
![](https://i-blog.csdnimg.cn/blog_migrate/4ceef65887f5341ce8f6bb62f15f7a8d.png)
15、SysTic
精确延时
#include "stm32f10x.h"
#define LED GPIO_Pin_2 //定义LED对应的管脚
void RCC_Configuration(void); //时钟配置
void TIM_Configuration(void);
void NVIC_Configuration(void); //NVIC配置
void GPIO_Configuration(void); //GPIO配置
int main(void)
{
RCC_Configuration();//配置时钟
GPIO_Configuration(); //配置GPIO, 注意,一定要先配置GPIO,在配置TIM和NVIC,否则无效
TIM_Configuration();
NVIC_Configuration();//配置NVIC
GPIO_ResetBits(GPIOA, LED);//PBA清零,LED亮
while(1){}
}
void RCC_Configuration(void)//时钟配置子程序
{
SystemInit(); //72MHz
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);//使能GPIOD的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能TIM2的时钟
}
void GPIO_Configuration(void) //GPIO配置
{ /*管脚设置*/
GPIO_InitTypeDef GPIO_InitStructure;//声明GPIO初始化结构体变量
GPIO_InitStructure.GPIO_Pin = LED;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
void NVIC_Configuration(void) //NVIC配置
{ //配置NVIC相应的优先级位
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; ;// 设置TIM2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 子优先级为 0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 串口中断使能
NVIC_Init(&NVIC_InitStructure);
}
void TIM_Configuration(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能TIM2的时钟
TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
TIM_BaseInitStructure.TIM_Prescaler = 36000-1; //预分频数值,72 000 000/36000=2000Hz
TIM_BaseInitStructure.TIM_Period = 1000-1; //预装载值,从0记数至1000后,产生中断信号,累计0.5s
TIM_BaseInitStructure.TIM_ClockDivision = 0;
TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//上升计数模式
TIM_BaseInitStructure.TIM_RepetitionCounter = TIM_CKD_DIV1;//滤波器采样分频
TIM_TimeBaseInit(TIM2, &TIM_BaseInitStructure); //清中断,以免一启用中断后立即产生中断
TIM_UpdateRequestConfig(TIM2, TIM_UpdateSource_Regular);
//TIM_ClearFlag(TIM2, TIM_FLAG_Update);
//使能TIM2中断源
TIM_Cmd(TIM2, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//TIM2总开关:开启
}
void TIM2_IRQHandler(void){
if(TIM_GetITStatus(TIM2, TIM_IT_Update)== SET)
{
GPIOD->ODR ^= LED; //异或使LED状态改变
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); //清除中断标志
}
}
呼吸灯
#include "stm32f10x.h"
void RCC_Configuration(void);
void TIM_Configuration(void);
void GPIO_Configuration(void);
void PWM_Configuration(void);
void delay_ms(u16 time);
int led_fx = 1;
int led_dt = 0;
int main(void)
{
RCC_Configuration();
GPIO_Configuration(); // GPIO要先于 TIM和NVIC配置
TIM_Configuration();
PWM_Configuration();
TIM_Cmd(TIM1, ENABLE); // 使能TIM计时器,开始输出PWM
while(1)
{
delay_ms(5);
if(led_fx == 1)
{
led_dt++;
}
else
{
led_dt--;
}
if(led_dt > 300)
{
led_fx = 0;
}
else if(led_dt == 0)
{
led_fx = 1;
}
TIM_SetCompare1(TIM1, led_dt);
}
}
void RCC_Configuration(void)//配置时钟
{
SystemInit();
//开启GPIO的时钟和复用功能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
//开启TIM1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
}
void GPIO_Configuration(void) //GPIO配置
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM1, ENABLE); // 映射引脚,
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//??????50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_DeInit(TIM1); //重新将Timer设置为缺省值
TIM_InternalClockConfig(TIM1); //采用内部时钟给TIM2提供时钟源
TIM_TimeBaseStructure.TIM_Prescaler = 1-1; //预分频数值,72000 000/1=72000000
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //定时器时钟(CK_INT)频率与数字滤波器(ETR,TIx)
//使用的采样频率之间的分频比为1
TIM_TimeBaseStructure.TIM_Period = 300-1; //设置计数溢出大小
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置计数器模式为向上计数模式(+1)
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //将配置应用到TIM2中
}
void PWM_Configuration(void)
{
TIM_OCInitTypeDef TimOCInitStructure;
//设置缺省值
TIM_OCStructInit(&TimOCInitStructure);
//PWM模式1输出
TimOCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
//设置占空比 (Led亮度)
TimOCInitStructure.TIM_Pulse = 0;
// TIM输出比较极性高
TimOCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
//使能输出状态
TimOCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
//TIM1的CH4输出
TIM_OC1Init(TIM1, &TimOCInitStructure);
//设置TIM1的PWM输出为使能
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
void delay_ms(u16 time)
{
u16 i = 0;
while(time--)
{
i=12000;
while(i--);
}
}
TIM3产生4路PWM波
/**
2 ******************************************************************************
3 * @file TIM/PWM_Output/main.c
4 * @author MCD Application Team
5 * @version V3.5.0
6 * @date 08-April-2011
7 * @brief Main program body
8 ******************************************************************************
9 * @attention
10 // PA6===TIM3_Ch1, PA7===TIM3_Ch2
11 // PB0===TIM3_Ch3, PB1===TIM3_Ch4
12 */
#include "stm32f10x.h"
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
uint16_t CCR1_Val = 333;
uint16_t CCR2_Val = 249;
uint16_t CCR3_Val = 166;
uint16_t CCR4_Val = 83;
uint16_t PrescalerValue = 0;
/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
int main(void)
{
RCC_Configuration();// System Clocks Configuration
GPIO_Configuration();
/* TIM3:产生4路PWM信号,每路具有不同的占空比
TIM3CLK频率设置为SystemCoreClock (Hz);
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
35 TIM3的计数器时钟频率设置为24MHz,对应的预分频系数计算公式为:
36 - Prescaler = (TIM3CLK / TIM3 counter clock) - 1
37 SystemCoreClock=72 MHz
38
39 TIM3的工作频率为 36 KHz: TIM3 Frequency = TIM3 counter clock/(ARR + 1)
40 = 24 MHz / 666 = 36 KHz
41 TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 = 50%
42 TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR)* 100 = 37.5%
43 TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR)* 100 = 25%
44 TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR)* 100 = 12.5%
45 ----------------------------------------------------------------------- */
/* Compute the prescaler value */
PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; //计算产生24MHz频率的分频系数
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 666-1; //设置自重重装载寄存器(ARR)的计数值
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;//预分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置定时器时钟(CK_INT)频率与数字滤波器(ETR,TIx)使用
//的采样频率之间的分频比例的(与输入捕获相关),0表示滤波器的频率和定时器的频率是一样的
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //输出比较模式=PWM输出模式1 (PWM输出有两种模式)
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;//指定将要加载到捕获比较寄存器的脉冲值,当计数器计数到这个值时,电平发生跳变
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设置输出比较极性,当定时器计数值小于CCR1_Val时为高电平
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
/* PWM1 Mode configuration: Channel2 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
/* PWM1 Mode configuration: Channel3 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
//指定将要加载到捕获比较寄存器的脉冲值,当计数器计数到这个值时,电平发生跳变
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
/* PWM1 Mode configuration: Channel4 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
//指定将要加载到捕获比较寄存器的脉冲值,当计数器计数到这个值时,电平发生跳变
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
TIM_Cmd(TIM3, ENABLE);/* TIM3 enable counter */
while (1)
{}
}
void RCC_Configuration(void)
{
/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* GPIOA and GPIOB clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOA Configuration:TIM3 Channel1, 2, 3 and 4 as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // PA6===TIM3_Ch1, PA7===TIM3_Ch2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; // PB0===TIM3_Ch3, PB1===TIM3_Ch4
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
SysTic定时
#include "stm32f10x.h"
__IO uint32_t TimingDelay; //声明外部变量
void RCC_Configuration(void);
void SysTick_Configuration(void);
void NVIC_Configuration(void);
void GPIO_Configuration(void);
void delay_ms(__IO uint32_t nTime);
int main(void)
{
RCC_Configuration();//配置时钟
GPIO_Configuration(); // 要先配置管脚在配置
SysTick_Configuration();
NVIC_Configuration();
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
while(1)
{
delay_ms(500);
GPIOA->ODR^=GPIO_Pin_8;
}
}
void RCC_Configuration(void)
{
SystemInit(); //72MHz
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM7的时钟
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;//设置SysTic中断
//TIM3_IRQn; ;// @设置TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 中断使能
NVIC_Init(&NVIC_InitStructure);
}
void SysTick_Configuration(void)
{
SysTick->LOAD = 72000 - 1; //设置1ms重装值
SysTick->CTRL = 0x00000007; // 选用HCLK为中断源
}
void delay_ms(__IO uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0)
{};
}
extern __IO uint32_t TimingDelay;
void SysTick_Handler(void) //SysTick中断处理子程序
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
16、CMSIS RTOS
/*----------------------------------------------------------------------------
* CMSIS-RTOS 'main' function template
*---------------------------------------------------------------------------*/
#include "stm32f10x.h"
#define osObjectsPublic // define objects in main module
#include "osObjects.h" // RTOS object definitions
/*
* main: initialize and start the system
*/
#define ON 1
#define OFF 0
#define LED1(opt) ((opt) ? (GPIOA->BRR |= 1 << 8) : (GPIOA->BSRR |= 1 << 8))
#define LED2(opt) ((opt) ? (GPIOD->BRR |= 1 << 2) : (GPIOD->BSRR |= 1 << 2))
void LED_Init(void)
{
RCC->APB2ENR |= (1 << 2) | (1 << 5);
GPIOA->CRH &= 0xFFFFFFF0;
GPIOA->CRH |= 0x00000003; // PA8设置为推挽输出
GPIOD->CRL &= 0xFFFFF0FF;
GPIOD->CRL |= 0x00000300; //PD2设置为推挽输出
LED1(OFF);
LED2(OFF); // 关闭两个灯
}
void led_Thread1(void const *p_arg)
{
while(1)
{
LED1(ON);
osDelay(500);
LED1(OFF);
osDelay(500);
}
}
void led_Thread2(void const *p_arg)
{
for(;;)
{
LED2(OFF);
osDelay(500);
LED2(ON);
osDelay(500);
}
}
osThreadDef(led_Thread1, osPriorityNormal, 1, 0); // 定义线程1
osThreadDef(led_Thread2, osPriorityNormal, 1, 0); // 定义线程2
osThreadId T_led_ID1; //线程1的Id
osThreadId T_led_ID2; //线程2的Id
int main (void) {
osKernelInitialize (); // initialize CMSIS-RTOS
// initialize peripherals here
LED_Init();
// create 'thread' functions that start executing,
// example: tid_name = osThreadCreate (osThread(name), NULL);
T_led_ID1 = osThreadCreate(osThread(led_Thread1), NULL); // 线程1
T_led_ID2 = osThreadCreate(osThread(led_Thread2), NULL); // 线程2
osKernelStart (); // start thread execution
}
END(嵌入式课程结束)接下来自己走咯,之后的学习记录会重新开贴写
复制了一个学期的代码,再自己修修改改,大概就汇聚在这个上面。
上面几乎所有的类型都囊括了,以后读别人代码的时候,这些基础库函数初始化代码,就是支持我的修改的基石咯
接下来我的学习计划就是把硬件知识提高上来,能读得懂别人的代码,然后利用原子哥的资源,网络上的的各种代码,修修补补,改出自己想要的代码,自己想要的结果,至少我觉得,我现在走的路都是前人走过了,我写的代码也都是前人已经写过的,并且已经开源的,现在能读得懂,并且能改的出自己想要的结果,这个就是我当前很长一段时间的目标,等到了能自己写代码,让人阅读的时候,那我这篇博客的点击量一定会很高吧,毕竟这是大神菜鸡的时候,
哈哈,现在我是真的菜,还是那种没有本事却很跳的那种,不知道以后我回过头来看,我成长的痕迹,看我现在写下的所记录的东西,不知道那时,时间有没有磨平我的棱角,不知道我有没有实现最初的梦想,愿初心不忘,归来仍是少年!
齐鲁工业大学,机电楼A511
2018年6月5日 19:18:02