STM32个人笔记
目录
1、较精确的软件延时函数
2、GPIO的8种模式
3、嘀嗒定时器
4、按键软件消抖的写法
5、GPIO_CRL &=~(0x0F<<(4*0))的解析
6、灯闪程序的问题
7、按键硬件防抖的电路设计
8、基本定时器,通用定时器和高级定时器
9、三极管开关电路
10、EEPROM电路
11、OneNet平台HTTP数据报格式
12、USART中使用printf打印
13、IIC程序及EEPROM电路图
14、TIMER计数器溢出产生中断时间计算
15、PWM占空比计算
1、较精确的软件延时函数:
void delay_us ( unsigned int us ) { unsigned char n; while( us-- ) for( n=0;n<9; n++ ); } void delay_ms ( unsigned int ms ) { while( ms-- ) delay_us(1000); }
2、GPIO的8种模式:
GPIO_Mode_AIN //模拟输入 GPIO_Mode_IN_FLOATING //浮空输入 GPIO_Mode_IPD //下拉输入 GPIO_Mode_IPU //上拉输入 GPIO_Mode_Out_OD //开漏输出 GPIO_Mode_Out_PP //推挽输出 GPIO_Mode_AF_OD //开漏复用输出
GPIO_Mode_AF_PP //推挽复用输出
3、嘀嗒定时器:
delay.c内容:
#include "delay.h" void delay_us ( unsigned int us) //微秒级延时函数,嘀嗒定时器为24位向下计数器 { SysTick -> VAL = 0; //设置计数器初值为0,一共32位,24位可用 SysTick -> LOAD = 9*us; //每计9个数才是1us,这里和TIM定时器计数有区别 SysTick -> CTRL = 0x01; //使能计数器,第0位为使能位,置1使能,置0失能 while((SysTick ->CTRL) != 0x10001); //向下产生溢出后,产生中断标志,及判断16位是否置1 SysTick -> CTRL =0; //产生溢出后,产生中断标志的第16位被置1,此时再将第16位置0,以便下次计数 SysTick -> VAL =0; //设置计数器初值为0,一共32位,24位可用 } void delay_ms ( unsigned int ms) //毫秒级延时函数,嘀嗒定时器为24位向下计数器 { SysTick -> VAL = 0;//设置计数器初值为0,一共32位,24位可用 SysTick -> LOAD = 9000*ms;//这里计9000个数才是1ms,这里和TIM定时器计数有区别 SysTick -> CTRL = 0x01;//使能计数器,第0位为使能位,置1使能,置0失能 while((SysTick ->CTRL) != 0x10001);//向下产生溢出后,产生中断标志,及判断16位是否置1 SysTick -> CTRL =0;//产生溢出后,产生中断标志的第16位被置1,此时再将第16位置0,以便下次计数 SysTick -> VAL =0;//设置计数器初值为0,一共32位,24位可用 }
delay.h内容:
#ifndef __DELAY_H #define __DELAY_H #include "stm32f10x.h" void delay_us(unsigned int us); void delay_ms(unsigned int ms); #endif
4、按键软件消抖的写法:
if(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin_x)==0){ delay_ms(50); if(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin_x)==0){
//此处为按键按下所要实现的功能
}
}
5、GPIO_CRL &=~(0x0F<<(4*0))的解析:
“ ~(0x0F<<(4*0)) ” 的值为0xF0;
后写为:GPIO_CRL= GPIO_CRL & 0xF0;
假设GPIO_CRL的值为0100 1100
那么这条程序的作用:GPIO_CRL的值的低4位被置0,其他位不变。
6、灯闪程序的问题:
GPIO_SetBits(GPIOA, GPIO_Pin_8); SysTick_Delay_Ms(500); //系统精准的延时函数 GPIO_ResetBits(GPIOA, GPIO_Pin_8); SysTick_Delay_Ms(500);
要想实现灯闪,必须在灯亮及灭后加延时函数,否则无法实现目的,即考虑视觉停留问题!
7、按键硬件防抖的电路设计:
注:此处参照野火板子硬件防抖设计
8、基本定时器,通用定时器和高级定时器:
1. 时钟源
定时器时钟 TIMxCLK,即内部时钟 CK_INT,经 APB1 预分频器后分频提供,如果
APB1 预分频系数等于 1,则频率不变,否则频率乘以 2,库函数中 APB1 预分频的系
数是 2,即 PCLK1=36M,所以定时器时钟 TIMxCLK=36*2=72M 。
2. 计数器时钟
定时器时钟经过 PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数。PSC 是一个
16 位的预分频器,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。
具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)。
3. 计数器
计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达
到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
4. 自动重装载寄存器
自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数
值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
5. 定时时间的计算
定时器的定时时间等于计数器的中断周期乘以中断的次数。计数器在 CK_CNT 的驱动
下,计一个数的时间则是 CK_CLK 的倒数,等于:1/(TIMxCLK/(PSC+1)),产生一次中
断的时间则等于:1/(CK_CLK * ARR)。如果在中断服务程序里面设置一个变量 time,用
来记录中断的次数,那么就可以计算出我们需要的定时时间等于: 1/CK_CLK *(ARR+1)*time。
例:定时器的时钟为72Mhz(72000000hz),我们让计数器时钟对定时器时钟36000分频(最大65536),那么计数器时钟CK_CNT=TIMxCLK/(PSC+1);
那么 CK_CNT=72000000/(35999+1);
计一个数的时间为:CK_CLK=1/CK_CNT ;
那么计一个数的时间为:1/( 72000000/(35999+1)) 即 (35999+1)/ 72000000 = 0.0005s=500us;
高级定时器的输入捕获解析:
高级控制器功能框图
stm32f0x数据手册
现在我们用PA0端口作为输入捕获的通道:
开启TIM5的时钟、总线APB1的时钟及GPIOA的时钟:
RCC_APB1PeriphClockCmd;
RCC_APB1Periph_TIM5;
RCC_APB2Periph_GPIOA;
通道的使用:
TIM5_CH1 对应的 TIM_Channel_1
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//输入通道和捕获通道的方式为直连
TIM_ClearFlag(TIM5, TIM_FLAG_Update|TIM_IT_CC1);//直连就为TIM_IT_CC1,非直连就为TIM_IT_CC2
TIM_GetCapture1;//获取寄存器通道1的值
TIM_OC1PolarityConfig;//设置 TIM5 通道 1 极性
现在我们改用PA1端口作为输入捕获的通道2:
通道的使用:
TIM5_CH2 对应的 TIM_Channel_2
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//输入通道和捕获通道的方式为直连
TIM_ClearFlag(TIM5, TIM_FLAG_Update|TIM_IT_CC2);//直连就为TIM_IT_CC2,非直连就为TIM_IT_CC1,需要了解直连和非直连的区别
TIM_GetCapture2;//获取寄存器通道2的值
TIM_OC2PolarityConfig;//设置 TIM5 通道 2 极性
9、三极管开关电路
LED1改成5v直流电机的时候需要将R1电阻去掉
10、EEPROM电路
11、OneNet平台HTTP数据报格式
printf ( "POST /devices/设备号/datapoints HTTP/1.1\napi-key:xxxxxxxxxxxxxxxxxxxx\nHost:api.heclouds.com\nContent-Length:59\n\n{\"datastreams\":[{\"id\":\"数据流名称\",\"datapoints\":[{\"value\":xx}]}]}\r\n");
AT+CWMODE=3 //配置成 AP+STA模式。 AT+RST //复位。。。。。。。。 AT+CIFSR //获取设备ip。。。。。 AT+CWJAP_DEF="16s","1234567890" //连接指定热点。。。。 AT+CIPSTART="TCP","183.230.40.33",80 //连接指定端口。。。 AT+CIPMODE=1 //开启透传。。。。。。 AT+CIPSEND //开始透传。。。。。。
+++ //退出透传。。。。。。
POST /devices/设备号/datapoints HTTP/1.1
api-key:xxxxxxxxxxxxxxx
Host:api.heclouds.com
Content-Length:60
{"datastreams":[{"id":"数据流名称","datapoints":[{"value":20}]}]}
12、USART中使用printf打印
usart.c内容:
#include "usart.h" static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* 嵌套向量中断控制器组选择 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 配置USART为中断源 */ NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ; /* 抢断优先级*/ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; /* 子优先级 */ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /* 使能中断 */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /* 初始化配置NVIC */ NVIC_Init(&NVIC_InitStructure); } void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; // 打开串口GPIO的时钟 DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); // 打开串口外设的时钟 DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE); // 将USART Tx的GPIO配置为推挽复用模式 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure); // 将USART Rx的GPIO配置为浮空输入模式 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); // 配置串口的工作参数 // 配置波特率 USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE; // 配置 针数据字长 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 配置停止位 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 配置校验位 USART_InitStructure.USART_Parity = USART_Parity_No ; // 配置硬件流控制 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 配置工作模式,收发一起 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 完成串口的初始化配置 USART_Init(DEBUG_USARTx, &USART_InitStructure); // 串口中断优先级配置 NVIC_Configuration(); // 使能串口接收中断 USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE); // 使能串口 USART_Cmd(DEBUG_USARTx, ENABLE); } /* 发送一个字节 */ void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data)//用法:Usart_SendByte(USART1,5); { USART_SendData(pUSARTx, data); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET ); } /* 发送两个字节的数据 */ void Usart_SendHalfWord(USART_TypeDef* pUSARTx, uint16_t data) { uint8_t temp_h,temp_l; temp_h = (data&0xff00) >> 8 ; temp_l = data&0xff; USART_SendData(pUSARTx, temp_h); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET ); USART_SendData(pUSARTx, temp_l); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET ); } /* 发送8位数据的数组 */ void Usart_SendArray(USART_TypeDef* pUSARTx, uint8_t *array,uint8_t num) { uint8_t i; for( i=0; i<num; i++ ) { Usart_SendByte(pUSARTx, array[i]); } while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET ); } /* 发送字符串 */ void Usart_SendStr(USART_TypeDef* pUSARTx, uint8_t *str)//用法:Usart_SendStr(USART1,"你好"); { uint8_t i=0; do { Usart_SendByte(pUSARTx, *(str+i)); i++; }while(*(str+i) != '\0'); while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET ); } //重定向c库函数printf到串口,重定向后可使用printf函数 int fputc(int ch, FILE *f)//用法:printf( "这是一个串口打印实验\n" ); { /* 发送一个字节数据到串口 */ USART_SendData(DEBUG_USARTx, (uint8_t) ch); /* 等待发送完毕 */ while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); return (ch); } ///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数 int fgetc(FILE *f) { /* 等待串口输入数据 */ while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET); return (int)USART_ReceiveData(DEBUG_USARTx); }
usart.h内容:
#ifndef __BSP_USART_H #define __BSP_USART_H #include "stm32f10x.h" #include <stdio.h> #define DEBUG_USART1 1 #define DEBUG_USART2 0 #define DEBUG_USART3 0 #define DEBUG_USART4 0 #define DEBUG_USART5 0 #if DEBUG_USART1 // 串口1-USART1 #define DEBUG_USARTx USART1 #define DEBUG_USART_CLK RCC_APB2Periph_USART1 #define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10 #define DEBUG_USART_IRQ USART1_IRQn #define DEBUG_USART_IRQHandler USART1_IRQHandler #elif DEBUG_USART2 //串口2-USART2 #define DEBUG_USARTx USART2 #define DEBUG_USART_CLK RCC_APB1Periph_USART2 #define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_2 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_3 #define DEBUG_USART_IRQ USART2_IRQn #define DEBUG_USART_IRQHandler USART2_IRQHandler #elif DEBUG_USART3 //串口3-USART3 #define DEBUG_USARTx USART3 #define DEBUG_USART_CLK RCC_APB1Periph_USART3 #define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOB) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOB #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10 #define DEBUG_USART_RX_GPIO_PORT GPIOB #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11 #define DEBUG_USART_IRQ USART3_IRQn #define DEBUG_USART_IRQHandler USART3_IRQHandler #elif DEBUG_USART4 //串口4-UART4 #define DEBUG_USARTx UART4 #define DEBUG_USART_CLK RCC_APB1Periph_UART4 #define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOC #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10 #define DEBUG_USART_RX_GPIO_PORT GPIOC #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11 #define DEBUG_USART_IRQ UART4_IRQn #define DEBUG_USART_IRQHandler UART4_IRQHandler #elif DEBUG_USART5 //串口5-UART5 #define DEBUG_USARTx UART5 #define DEBUG_USART_CLK RCC_APB1Periph_UART5 #define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd #define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOC #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_12 #define DEBUG_USART_RX_GPIO_PORT GPIOD #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_2 #define DEBUG_USART_IRQ UART5_IRQn #define DEBUG_USART_IRQHandler UART5_IRQHandler #endif void USART_Config(void); void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data); void Usart_SendHalfWord(USART_TypeDef* pUSARTx, uint16_t data); void Usart_SendArray(USART_TypeDef* pUSARTx, uint8_t *array,uint8_t num); void Usart_SendStr(USART_TypeDef* pUSARTx, uint8_t *str); #endif /* __BSP_USART_H */
13、IIC程序及EEPROM电路图
iic.c内容:
#include "iic.h" #include "delay.h" //IIC初始化 void iic_init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN|IIC_SDA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //IIC_SCL_PIN|IIC_SDA_PIN推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(IIC_GPIO, &GPIO_InitStructure); GPIO_SetBits(IIC_GPIO,IIC_SCL_PIN|IIC_SDA_PIN); //设置为1 IIC_SCL_H; IIC_SDA_H; } //数据线输出模式 void iic_sda_out(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //IIC_SCL_PIN|IIC_SDA_PIN推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(IIC_GPIO, &GPIO_InitStructure); } //数据线输入模式 void iic_sda_in(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //IIC_SCL_PIN|IIC_SDA_PIN推挽输出 GPIO_Init(IIC_GPIO, &GPIO_InitStructure); } //IIC数据传送启动信号 //SCL为高电平的时候,SDA下降沿 void iic_start(void) { iic_sda_out(); //SDA线输出 IIC_SDA_H; //SDA为高电平 IIC_SCL_H; //SCL为高电平 delay_us(5); IIC_SDA_L; //SDA下降沿 delay_us(6); IIC_SCL_L; } //IIC数据传送停止信号 //SCL为高电平时,SDA上升沿 void iic_stop(void) { iic_sda_out(); //SDA线输出 IIC_SCL_L; //SDA为低电平 IIC_SDA_L; IIC_SCL_H; delay_us(6); IIC_SDA_H; //SCL高电平 delay_us(6); } //应答信号 void iic_ACK(void) { IIC_SCL_L; //SCL低电平 iic_sda_out(); IIC_SDA_L; //SDA为低电平 delay_us(2); IIC_SCL_H; //SCL高电平 delay_us(5); IIC_SCL_L; //SCL低电平 } //非应答信号 void iic_NACK(void) { IIC_SCL_L; //SCL低电平 iic_sda_out(); IIC_SDA_H; //SDA为高电平 delay_us(2); IIC_SCL_H; //SCL高电平 delay_us(5); IIC_SCL_L; //SCL低电平 } //IIC等待应答 u8 iic_wf_ack(void) { u8 times=0; iic_sda_in();//设置SDA为输入模式 IIC_SDA_H; delay_us(1); IIC_SCL_H; delay_us(1); while(GPIO_ReadInputDataBit(IIC_GPIO, IIC_SDA_PIN))//超时应答判断 { times++; delay_us(1); if(times>250) { iic_stop(); return 1; } } IIC_SCL_L; return 0; } //IIC发送数据 void iic_SendByte(u8 txd) { u8 i; iic_sda_out();//设置SDA为输出模式 IIC_SCL_L; for(i=0;i<8;i++) { if((txd&0x80)>>7) IIC_SDA_H; else IIC_SDA_L; txd <<=1; delay_us(2); IIC_SCL_H; delay_us(2); IIC_SCL_L; delay_us(2); } } //IIC读取数据 u8 iic_ReadByte(u8 ack) { u8 i,Receive=0; iic_sda_in();//设置SDA为输入模式 for(i=0;i<8;i++) { IIC_SCL_L; delay_us(2); IIC_SCL_H; Receive<<= 1; if(GPIO_ReadInputDataBit(IIC_GPIO, IIC_SDA_PIN)) Receive|=0x01; delay_us(1); } if(ack) iic_ACK(); else iic_NACK(); return Receive;//返回最终读取到的值 } void AT24C02_WriteOneByte(u8 addr,u8 dt) { iic_start(); iic_SendByte(0xA0); iic_wf_ack(); iic_SendByte(addr); iic_wf_ack(); iic_SendByte(dt); iic_wf_ack(); iic_stop(); delay_ms(10); } u8 AT24C02_ReadOneByte(u8 addr) { u8 temp=0; iic_start(); iic_SendByte(0xA0); iic_wf_ack(); iic_SendByte(addr); iic_wf_ack(); iic_start(); iic_SendByte(0xA1); iic_wf_ack(); temp=iic_ReadByte(0); iic_stop(); return temp; }
iic.h内容:
#ifndef __IIC_H #define __IIC_H #include "stm32f10x.h" #define IIC_GPIO GPIOB #define IIC_SCL_PIN GPIO_Pin_6 #define IIC_SDA_PIN GPIO_Pin_7 #define IIC_SCL_H GPIO_SetBits(GPIOB, GPIO_Pin_6) #define IIC_SCL_L GPIO_ResetBits(GPIOB, GPIO_Pin_6) #define IIC_SDA_H GPIO_SetBits(GPIOB, GPIO_Pin_7) #define IIC_SDA_L GPIO_ResetBits(GPIOB, GPIO_Pin_7) void iic_init(void); void iic_sda_out(void); void iic_sda_in(void); void iic_start(void); void iic_stop(void); void iic_ACK(void); void iic_NACK(void); u8 iic_wf_ack(void); void iic_SendByte(u8 txd); u8 iic_ReadByte(u8 ack); void AT24C02_WriteOneByte(u8 addr,u8 dat); u8 AT24C02_ReadOneByte(u8 addr); #endif
main.c内容:
#include "stm32f10x.h" #include "bsp_usart.h" #include "delay.h" #include "iic.h" int main(void) { u16 value=12;//想要写进去的值 u16 ADD=16;//写EEPROM的指定地址 USART_Config(); iic_init(); while(1){ AT24C02_WriteOneByte(ADD,value); printf("写进去的数据是:%d\r\n",value); printf("读出来的数据是:%d\r\n",AT24C02_ReadOneByte(0)+1); delay_ms(1000); } } /*********************************************END OF FILE**********************/
14、TIMER溢出计算公式:
T=1/f;分频系数是指系统总时钟(f=72Mhz) 分给定时器的时钟,psc*(1/f)=定时器的时钟周期,也就是记一次数所用时间,arr是定时器的重装载值,
15、PWM频率计算
具体的周期计算公式为:周期=(arr+1)*(psc+1)/CLK
如产生20ms的周期:
(200 * 7200)/72000000 = 0.02s = 20ms
设置占空比:
TIM_SetCompare2(TIM3,175);
175 /(arr + 1) = xx%