赞
踩
#include "sys.h" #include "delay.h" #include "usart.h" #include "bsp_adc.h" #include "bsp_advanced_timer.h" #include "bsp_i2c_gpio.h" #include "OLED_I2C.h" #include "bsp_systick.h" #include "bsp_led.h" #include <math.h> #define pi 3.1415926535 #define accur 0.015295 extern uint16_t ConvData;//ADC采样数据 extern unsigned char BMP1[]; int main() { uint8_t x; LED_Init(); OLED_Init(); /* OLED初始化 */ ADCx_Init(); AdvancedTim_Init(); Before_State_Update(accur*ConvData); OLED_CLS(); while(1) { for(x=0;x<128;x=(x+1)%128) { OLED_DrawWave(x,accur*ConvData); } }
#include "bsp_adc.h" uint16_t ConvData; static void ADCx_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; /*开时钟*/ RCC_APB2PeriphClockCmd(ADCx_PORT_CLK, ENABLE); /*配置参数*/ GPIO_InitStruct.GPIO_Pin=ADCx_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;/*模拟输入模式*/ /*写入寄存器*/ GPIO_Init(ADCx_PORT, &GPIO_InitStruct); } static void ADCx_Config(void) { ADC_InitTypeDef ADC_InitStruct; /*打开ADC时钟*/ RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE); /*配置参数*/ ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;/*独立模式*/ ADC_InitStruct.ADC_ContinuousConvMode=ENABLE;/*连续转换*/ ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;/*数据右对齐*/ ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;/*不使用外部硬件触发*/ ADC_InitStruct.ADC_NbrOfChannel=ADCx_CHx;/*ADC是哪个通道*/ ADC_InitStruct.ADC_ScanConvMode=DISABLE;/*不使用连续扫描*/ /*将参数写入寄存器*/ ADC_Init(ADC_x, &ADC_InitStruct); /*设置ADC_CLK*/ RCC_ADCCLKConfig(RCC_PCLK2_Div6); /*规则通道设置,通道,采样顺序,采样时间*/ ADC_RegularChannelConfig(ADC_x, ADCx_CHx, 1, ADC_SampleTime_1Cycles5); /*ADC使能*/ ADC_Cmd(ADC_x, ENABLE); /*校验ADC*/ ADC_StartCalibration(ADC_x); while(ADC_GetCalibrationStatus(ADC_x)==RESET); /*DMA设置*/ ADC_DMACmd(ADC_x, ENABLE); /*ADC软件触发,开始转换*/ ADC_SoftwareStartConvCmd(ADC_x, ENABLE); } static void ADCx_DMA_Config(void) { DMA_InitTypeDef DMA_InitStruct; /*打开DMA时钟*/ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /*配置DMA参数*/ DMA_InitStruct.DMA_PeripheralBaseAddr=(uint32_t)(&(ADC_x->DR));/*ADC的数据寄存器*/ DMA_InitStruct.DMA_MemoryBaseAddr=(uint32_t)(&ConvData);/*存储器地址*/ DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralSRC;/*外设为源*/ DMA_InitStruct.DMA_BufferSize=1;/*数据的个数为1*/ DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;/*外设地址不增加*/ DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Disable;/*存储器地址不增加*/ DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord; /*16位数据,所以是半字*/ DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord; DMA_InitStruct.DMA_Mode=DMA_Mode_Circular;/*这里是指数据循环不停地发送*/ DMA_InitStruct.DMA_Priority=DMA_Priority_High;/*DMA优先级设为高*/ DMA_InitStruct.DMA_M2M=DMA_M2M_Disable;/*不使能存储器到存储器*/ /*将参数写入寄存器*/ DMA_Init(ADCx_DMA_CHx, &DMA_InitStruct); /*使能DMA*/ DMA_Cmd(ADCx_DMA_CHx, ENABLE); } void ADCx_Init(void) { ADCx_GPIO_Config(); ADCx_DMA_Config(); ADCx_Config(); }
#ifndef _BSP_ADC_H_ #define _BSP_ADC_H_ #include "stm32f10x.h" /*GPIO*/ #define ADCx_PORT_CLK RCC_APB2Periph_GPIOA #define ADCx_PIN GPIO_Pin_7 #define ADCx_PORT GPIOA /*ADC*/ #define ADC_x ADC1 #define ADCx_CLK RCC_APB2Periph_ADC1 #define ADCx_CHx ADC_Channel_7 /*DMA*/ #define ADCx_DMA_CLK RCC_AHBPeriph_DMA1 #define ADCx_DMA_CHx DMA1_Channel1 void ADCx_Init(void); #endif //_BSP_ADC_H_
#include "bsp_advanced_timer.h" static void AdvancedTim_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; /*开时钟*/ TIMx_CH1_GPIO_CLK_CMD(TIMx_CH1_GPIO_CLK, ENABLE); TIMx_CH1N_GPIO_CLK_CMD(TIMx_CH1N_GPIO_CLK, ENABLE); TIMx_BKIN_GPIO_CLK_CMD(TIMx_BKIN_GPIO_CLK ,ENABLE); /*设置参数1*/ GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Pin=TIMx_CH1_GPIO_PIN; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; /*写参数*/ GPIO_Init(TIMx_CH1_GPIO_PORT, &GPIO_InitStruct); /*设置参数2*/ GPIO_InitStruct.GPIO_Pin=TIMx_CH1N_GPIO_PIN; /*写参数*/ GPIO_Init(TIMx_CH1N_GPIO_PORT, &GPIO_InitStruct); /*设置参数3*/ GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Pin=TIMx_BKIN_GPIO_PIN; /*写参数*/ GPIO_Init(TIMx_BKIN_GPIO_PORT, &GPIO_InitStruct); } static void AdvancedTim_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_OCInitTypeDef TIM_OCInitStruct; TIM_BDTRInitTypeDef TIM_BDTRInitStruct; /*开时钟*/ RCC_APB2PeriphClockCmd(ADVANCED_TIM_CLK, ENABLE); /*配置时基参数*/ TIM_TimeBaseInitStruct.TIM_Prescaler=ADVANCED_TIM_PSC;/*预分频因子*/ TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;/*向上计数*/ TIM_TimeBaseInitStruct.TIM_Period=ADVANCED_TIM_ARR;/*周期*/ TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;/*Tdts:这里会与死区时间有关*/ TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;/*不使用重复计数器*/ /*写参数*/ TIM_TimeBaseInit(ADVANCED_TIM, &TIM_TimeBaseInitStruct); /*配置输出比较的参数*/ TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;/*PWM模式一*/ TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;/*主通道使能*/ TIM_OCInitStruct.TIM_OutputNState=TIM_OutputNState_Enable;/*互补通道使能*/ TIM_OCInitStruct.TIM_Pulse=ADVANCED_TIM_CCR;/*占空比*/ TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;/*主通道高电平为有效*/ TIM_OCInitStruct.TIM_OCNPolarity=TIM_OCNPolarity_High;/*互补通道高电平为有效*/ TIM_OCInitStruct.TIM_OCIdleState=TIM_OCIdleState_Reset;/*刹车后的输出状态*/ TIM_OCInitStruct.TIM_OCNIdleState=TIM_OCNIdleState_Reset; /*写参数*/ TIM_OC1Init(ADVANCED_TIM, &TIM_OCInitStruct); TIM_OC1PreloadConfig(ADVANCED_TIM, TIM_OCPreload_Enable); /*配置死区刹车寄存器*/ TIM_BDTRInitStruct.TIM_OSSRState=TIM_OSSRState_Enable; TIM_BDTRInitStruct.TIM_OSSIState=TIM_OSSIState_Enable; TIM_BDTRInitStruct.TIM_LOCKLevel=TIM_LOCKLevel_OFF; TIM_BDTRInitStruct.TIM_DeadTime=7; /*死区时间97ns*/ TIM_BDTRInitStruct.TIM_Break=TIM_Break_Enable;/*使能刹车功能*/ TIM_BDTRInitStruct.TIM_BreakPolarity=TIM_BreakPolarity_High;/*当刹车通道为高电平时停止输出*/ TIM_BDTRInitStruct.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable; TIM_BDTRConfig(ADVANCED_TIM, &TIM_BDTRInitStruct); TIM_Cmd(ADVANCED_TIM, ENABLE); TIM_CtrlPWMOutputs(ADVANCED_TIM, ENABLE); } void AdvancedTim_Init(void) { AdvancedTim_GPIO_Config(); AdvancedTim_Config(); }
#ifndef _BSP_ADVANCED_TIMER_H_ #define _BSP_ADVANCED_TIMER_H_ #include "stm32f10x.h" /*GPIO*/ #define TIMx_CH1_GPIO_PORT GPIOA #define TIMx_CH1_GPIO_PIN GPIO_Pin_8 #define TIMx_CH1_GPIO_CLK RCC_APB2Periph_GPIOA #define TIMx_CH1_GPIO_CLK_CMD RCC_APB2PeriphClockCmd #define TIMx_CH1N_GPIO_PORT GPIOB #define TIMx_CH1N_GPIO_PIN GPIO_Pin_13 #define TIMx_CH1N_GPIO_CLK RCC_APB2Periph_GPIOB #define TIMx_CH1N_GPIO_CLK_CMD RCC_APB2PeriphClockCmd #define TIMx_BKIN_GPIO_PORT GPIOB #define TIMx_BKIN_GPIO_PIN GPIO_Pin_12 #define TIMx_BKIN_GPIO_CLK RCC_APB2Periph_GPIOB #define TIMx_BKIN_GPIO_CLK_CMD RCC_APB2PeriphClockCmd /*Advanced Timer*/ #define ADVANCED_TIM TIM1 #define ADVANCED_TIM_CLK RCC_APB2Periph_TIM1 #define ADVANCED_TIM_PSC_SET 36 #define ADVANCED_TIM_PSC (ADVANCED_TIM_PSC_SET-1) #define ADVANCED_TIM_ARR_SET 65536 #define ADVANCED_TIM_ARR (ADVANCED_TIM_ARR_SET-1) #define ADVANCED_TIM_CCR_SET 12000 #define ADVANCED_TIM_CCR (ADVANCED_TIM_CCR_SET) void AdvancedTim_Init(void); #endif//_BSP_ADVANCED_TIMER_H_
/** ****************************************************************************** * @file bsp_i2c_gpio.c * @version V1.0 * @date 2013-xx-xx * @brief 用gpio模拟i2c总线, 适用于STM32系列CPU。该模块不包括应用层命令帧,仅包括I2C总线基本操作函数。 ****************************************************************************** * @attention * * 实验平台:野火 F103-MINI STM32 开发板 * 论坛 :http://www.firebbs.cn * 淘宝 :https://fire-stm32.taobao.com * ****************************************************************************** */ /* 应用说明: 在访问I2C设备前,请先调用 i2c_CheckDevice() 检测I2C设备是否正常 */ #include "bsp_i2c_gpio.h" #include "stm32f10x.h" /* ********************************************************************************************************* * 函 数 名: i2c_Delay * 功能说明: I2C总线位延迟,最快400KHz * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ static void i2c_Delay(void) { //uint8_t i; /* 下面的时间是通过逻辑分析仪测试得到的。 工作条件:CPU主频72MHz ,MDK编译环境,1级优化 循环次数为10时,SCL频率 = 205KHz 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us */ //for (i = 0; i < 10; i++); } /* ********************************************************************************************************* * 函 数 名: i2c_Start * 功能说明: CPU发起I2C总线启动信号 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void i2c_Start(void) { /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */ OLED_I2C_SDA_1(); OLED_I2C_SCL_1(); i2c_Delay(); OLED_I2C_SDA_0(); i2c_Delay(); OLED_I2C_SCL_0(); i2c_Delay(); } /* ********************************************************************************************************* * 函 数 名: i2c_Start * 功能说明: CPU发起I2C总线停止信号 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void i2c_Stop(void) { /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */ OLED_I2C_SDA_0(); OLED_I2C_SCL_1(); i2c_Delay(); OLED_I2C_SDA_1(); } /* ********************************************************************************************************* * 函 数 名: i2c_SendByte * 功能说明: CPU向I2C总线设备发送8bit数据 * 形 参:_ucByte : 等待发送的字节 * 返 回 值: 无 ********************************************************************************************************* */ void i2c_SendByte(uint8_t _ucByte) { uint8_t i; /* 先发送字节的高位bit7 */ for (i = 0; i < 8; i++) { if (_ucByte & 0x80) { OLED_I2C_SDA_1(); } else { OLED_I2C_SDA_0(); } i2c_Delay(); OLED_I2C_SCL_1(); i2c_Delay(); OLED_I2C_SCL_0(); if (i == 7) { OLED_I2C_SDA_1(); // 释放总线 } _ucByte <<= 1; /* 左移一个bit */ i2c_Delay(); } } /* ********************************************************************************************************* * 函 数 名: i2c_ReadByte * 功能说明: CPU从I2C总线设备读取8bit数据 * 形 参:无 * 返 回 值: 读到的数据 ********************************************************************************************************* */ uint8_t i2c_ReadByte(void) { uint8_t i; uint8_t value; /* 读到第1个bit为数据的bit7 */ value = 0; for (i = 0; i < 8; i++) { value <<= 1; OLED_I2C_SCL_1(); i2c_Delay(); if (OLED_I2C_SDA_READ()) { value++; } OLED_I2C_SCL_0(); i2c_Delay(); } return value; } /* ********************************************************************************************************* * 函 数 名: i2c_WaitAck * 功能说明: CPU产生一个时钟,并读取器件的ACK应答信号 * 形 参:无 * 返 回 值: 返回0表示正确应答,1表示无器件响应 ********************************************************************************************************* */ uint8_t i2c_WaitAck(void) { uint8_t re; OLED_I2C_SDA_1(); /* CPU释放SDA总线 */ i2c_Delay(); OLED_I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */ i2c_Delay(); if (OLED_I2C_SDA_READ()) /* CPU读取SDA口线状态 */ { re = 1; } else { re = 0; } OLED_I2C_SCL_0(); i2c_Delay(); return re; } /* ********************************************************************************************************* * 函 数 名: i2c_Ack * 功能说明: CPU产生一个ACK信号 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void i2c_Ack(void) { OLED_I2C_SDA_0(); /* CPU驱动SDA = 0 */ i2c_Delay(); OLED_I2C_SCL_1(); /* CPU产生1个时钟 */ i2c_Delay(); OLED_I2C_SCL_0(); i2c_Delay(); OLED_I2C_SDA_1(); /* CPU释放SDA总线 */ } /* ********************************************************************************************************* * 函 数 名: i2c_NAck * 功能说明: CPU产生1个NACK信号 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void i2c_NAck(void) { OLED_I2C_SDA_1(); /* CPU驱动SDA = 1 */ i2c_Delay(); OLED_I2C_SCL_1(); /* CPU产生1个时钟 */ i2c_Delay(); OLED_I2C_SCL_0(); i2c_Delay(); } /* ********************************************************************************************************* * 函 数 名: i2c_CfgGpio * 功能说明: 配置I2C总线的GPIO,采用模拟IO的方式实现 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void i2c_CfgGpio(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(OLED_RCC_I2C_PORT, ENABLE); /* 打开GPIO时钟 */ GPIO_InitStructure.GPIO_Pin = OLED_I2C_SCL_PIN | OLED_I2C_SDA_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; /* 开漏输出 */ GPIO_Init(OLED_GPIO_PORT_I2C, &GPIO_InitStructure); /* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */ i2c_Stop(); }
#ifndef _BSP_I2C_GPIO_H #define _BSP_I2C_GPIO_H #include <inttypes.h> #define OLED_I2C_WR 0 /* 写控制bit */ #define OLED_I2C_RD 1 /* 读控制bit */ /* 定义I2C总线连接的GPIO端口, 用户只需要修改下面4行代码即可任意改变SCL和SDA的引脚 */ #define OLED_GPIO_PORT_I2C GPIOB /* GPIO端口 */ #define OLED_RCC_I2C_PORT RCC_APB2Periph_GPIOB /* GPIO端口时钟 */ #define OLED_I2C_SCL_PIN GPIO_Pin_6 /* 连接到SCL时钟线的GPIO */ #define OLED_I2C_SDA_PIN GPIO_Pin_7 /* 连接到SDA数据线的GPIO */ /* 定义读写SCL和SDA的宏,已增加代码的可移植性和可阅读性 */ #if 0 /* 条件编译: 1 选择GPIO的库函数实现IO读写 */ #define OLED_I2C_SCL_1() GPIO_SetBits(OLED_GPIO_PORT_I2C, OLED_I2C_SCL_PIN) /* SCL = 1 */ #define OLED_I2C_SCL_0() GPIO_ResetBits(OLED_GPIO_PORT_I2C, OLED_I2C_SCL_PIN) /* SCL = 0 */ #define OLED_I2C_SDA_1() GPIO_SetBits(OLED_GPIO_PORT_I2C, OLED_I2C_SDA_PIN) /* SDA = 1 */ #define OLED_I2C_SDA_0() GPIO_ResetBits(OLED_GPIO_PORT_I2C, OLED_I2C_SDA_PIN) /* SDA = 0 */ #define OLED_I2C_SDA_READ() GPIO_ReadInputDataBit(OLED_GPIO_PORT_I2C, OLED_I2C_SDA_PIN) /* 读SDA口线状态 */ #else /* 这个分支选择直接寄存器操作实现IO读写 */ /* 注意:如下写法,在IAR最高级别优化时,会被编译器错误优化 */ #define OLED_I2C_SCL_1() OLED_GPIO_PORT_I2C->BSRR = OLED_I2C_SCL_PIN /* SCL = 1 */ #define OLED_I2C_SCL_0() OLED_GPIO_PORT_I2C->BRR = OLED_I2C_SCL_PIN /* SCL = 0 */ #define OLED_I2C_SDA_1() OLED_GPIO_PORT_I2C->BSRR = OLED_I2C_SDA_PIN /* SDA = 1 */ #define OLED_I2C_SDA_0() OLED_GPIO_PORT_I2C->BRR = OLED_I2C_SDA_PIN /* SDA = 0 */ #define OLED_I2C_SDA_READ() ((OLED_GPIO_PORT_I2C->IDR & OLED_I2C_SDA_PIN) != 0) /* 读SDA口线状态 */ #endif void i2c_Start(void); void i2c_Stop(void); void i2c_SendByte(uint8_t _ucByte); uint8_t i2c_ReadByte(void); uint8_t i2c_WaitAck(void); void i2c_Ack(void); void i2c_NAck(void); void i2c_CfgGpio(void); #endif
#include "OLED_I2C.h" #include "bsp_i2c_gpio.h" #include "bsp_systick.h" #include "codetab.h" uint8_t DataBuffer[8][128]; uint8_t Bef[3];//保存前一个数据的几个参数1.要写在第几页2.0x01要移动几位3.写什么数据 uint8_t Cur[3];//当前前一个数据1.要写在第几页2.0x01要移动几位3.写什么数据 /* ********************************************************************************************************* * 函 数 名: i2c_CheckDevice * 功能说明: 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在 * 形 参:_Address:设备的I2C总线地址 * 返 回 值: 返回值 0 表示正确, 返回1表示未探测到 ********************************************************************************************************* */ uint8_t OLED_CheckDevice(uint8_t _Address) { uint8_t ucAck; i2c_Start(); /* 发送启动信号 */ i2c_SendByte(_Address|OLED_I2C_WR);/* 发送设备地址 */ ucAck = i2c_WaitAck(); /* 检测设备的ACK应答 */ i2c_Stop(); /* 发送停止信号 */ return ucAck; } /** * @brief I2C_WriteByte,向OLED寄存器地址写一个byte的数据 * @param addr:寄存器地址 * data:要写入的数据 * @retval 无 */ void I2C_WriteByte(uint8_t addr,uint8_t data){ i2c_Start();//开启I2C总线 /* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */ i2c_SendByte(OLED_ADDRESS|OLED_I2C_WR); /*等待ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* OLED器件无应答 */ } i2c_SendByte(addr);//发送寄存器地址 /*等待ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* OLED器件无应答 */ } i2c_SendByte(data);//发送数据 /*等待ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* OLED器件无应答 */ } /* 发送I2C总线停止信号 */ i2c_Stop(); cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */ /* 发送I2C总线停止信号 */ i2c_Stop(); } /** * @brief WriteCmd,向OLED写入命令 * @param I2C_Command:命令代码 * @retval 无 */ void WriteCmd(unsigned char I2C_Command)//写命令 { I2C_WriteByte(0x00, I2C_Command); } /** * @brief WriteDat,向OLED写入数据 * @param I2C_Data:数据 * @retval 无 */ void WriteDat(unsigned char I2C_Data)//写数据 { I2C_WriteByte(0x40, I2C_Data); } /** * @brief OLED_Init,初始化OLED * @param 无 * @retval 无 */ void OLED_Init(void) { i2c_CfgGpio(); /*I2C总线的GPIO初始化*/ Delay_ms(1000); // 1s,这里的延时很重要,上电后延时,没有错误的冗余设计 WriteCmd(0xAE); //display off WriteCmd(0x20); //Set Memory Addressing Mode WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7 WriteCmd(0xc8); //Set COM Output Scan Direction WriteCmd(0x00); //---set low column address WriteCmd(0x10); //---set high column address WriteCmd(0x40); //--set start line address WriteCmd(0x81); //--set contrast control register WriteCmd(0xff); //亮度调节 0x00~0xff WriteCmd(0xa1); //--set segment re-map 0 to 127 WriteCmd(0xa6); //--set normal display WriteCmd(0xa8); //--set multiplex ratio(1 to 64) WriteCmd(0x3F); // WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content WriteCmd(0xd3); //-set display offset WriteCmd(0x00); //-not offset WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency WriteCmd(0xf0); //--set divide ratio WriteCmd(0xd9); //--set pre-charge period WriteCmd(0x22); // WriteCmd(0xda); //--set com pins hardware configuration WriteCmd(0x12); WriteCmd(0xdb); //--set vcomh WriteCmd(0x20); //0x20,0.77xVcc WriteCmd(0x8d); //--set DC-DC enable WriteCmd(0x14); // WriteCmd(0xaf); //--turn on oled panel } /** * @brief OLED_SetPos,设置光标 * @param x,第几页 * y,第几列 * @retval 无 */ void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标 { WriteCmd(0xb0+x); WriteCmd((y&0x0f)|0x00);//LOW WriteCmd(((y&0xf0)>>4)|0x10);//HIGHT } /** * @brief OLED_Fill,填充整个屏幕 * @param fill_Data:要填充的数据 * @retval 无 */ void OLED_Fill(void)//全屏填充 { uint8_t i,j; for(i=0;i<8;i++) { for(j=0;j<128;j++) { DataBuffer[i][j]=0xff; } } Write_DataBuffer(); } /** * @brief OLED_CLS,清屏 * @param 无 * @retval 无 */ void OLED_CLS(void)//清屏 { uint8_t i,j; for(i=0;i<8;i++) { for(j=0;j<128;j++) { DataBuffer[i][j]=0x00; } } Write_DataBuffer(); } /** * @brief OLED_ON,将OLED从休眠中唤醒 * @param 无 * @retval 无 */ void OLED_ON(void) { WriteCmd(0X8D); //设置电荷泵 WriteCmd(0X14); //开启电荷泵 WriteCmd(0XAF); //OLED唤醒 } /** * @brief OLED_OFF,让OLED休眠 -- 休眠模式下,OLED功耗不到10uA * @param 无 * @retval 无 */ void OLED_OFF(void) { WriteCmd(0X8D); //设置电荷泵 WriteCmd(0X10); //关闭电荷泵 WriteCmd(0XAE); //OLED休眠 } void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize) { // Parameters : x,y -- 起始点坐标(x:0~127, y:0~7); ch[] -- 要显示的字符串; TextSize -- 字符大小(1:6*8 ; 2:8*16) // Description : 显示codetab.h中的ASCII字符,有6*8和8*16可选择 unsigned char c = 0,i = 0,j = 0; switch(TextSize) { case 1: { while(ch[j] != '\0') { c = ch[j] - 32; if(x > 126) { x = 0; y++; } //OLED_SetPos(x,y); OLED_SetPos(y,x); for(i=0;i<6;i++) WriteDat(F6x8[c][i]); x += 6; j++; } }break; case 2: { while(ch[j] != '\0') { c = ch[j] - 32; if(x > 120) { x = 0; y++; } //OLED_SetPos(x,y); OLED_SetPos(y,x); for(i=0;i<8;i++) WriteDat(F8X16[c*16+i]); //OLED_SetPos(x,y+1); OLED_SetPos(y+1,x); for(i=0;i<8;i++) WriteDat(F8X16[c*16+i+8]); x += 8; j++; } }break; } } void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N) { // Parameters : x,y -- 起始点坐标(x:0~127, y:0~7); N:汉字在codetab.h中的索引 // Description : 显示codetab.h中的汉字,16*16点阵 unsigned char wm=0; unsigned int adder=32*N; //OLED_SetPos(x , y); OLED_SetPos(y,x); for(wm = 0;wm < 16;wm++) { WriteDat(F16x16[adder]); adder += 1; } //OLED_SetPos(x,y + 1); OLED_SetPos(y+1,x); for(wm = 0;wm < 16;wm++) { WriteDat(F16x16[adder]); adder += 1; } } void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]) { // Parameters : x0,y0 -- 起始点坐标(x0:0~127, y0:0~7); x1,y1 -- 起点对角线(结束点)的坐标(x1:1~128,y1:1~8) // Description : 显示BMP位图 unsigned int j=0; unsigned char x,y; if(y1%8==0) y = y1/8; else y = y1/8 + 1; for(y=y0;y<y1;y++) { //OLED_SetPos(x0,y); OLED_SetPos(y,x0); for(x=x0;x<x1;x++) { WriteDat(BMP[j++]); } } } void Before_State_Update(uint8_t y)//根据y的值,求出前一个数据的有关参数 { Bef[0]=7-y/8; Bef[1]=7-y%8; Bef[2]=1<<Bef[1]; } void Current_State_Update(uint8_t y)//根据Y值,求出当前数据的有关参数 { Cur[0]=7-y/8;//数据写在第几页 Cur[1]=7-y%8;//0x01要移动的位数 Cur[2]=1<<Cur[1];//要写什么数据 } /*0<=x<=127,0<=y<=63屏幕看作一个坐标轴,左下角是原点*/ void OLED_DrawPoint(uint8_t x,uint8_t y)/*这里x是横坐标,y是纵坐标,在(x,y)处画一个点*/ { if(x>127||y>63) return; uint8_t page,move,data; page=7-y/8;//数据写在第几页 move=7-y%8;//0x01要移动的位数 data=0x01<<move;//要写什么数据 OLED_SetPos(page,x); WriteDat(data); } void OLED_DrawWave(uint8_t x,uint8_t y) { int8_t page_sub; uint8_t page_buff,i,j; Current_State_Update(y);//根据Y值,求出当前数据的有关参数 page_sub=Bef[0]-Cur[0];//当前值与前一个值的页数相比较 //确定当前列,每一页应该写什么数据 if(page_sub>0) { page_buff=Bef[0]; OLED_SetPos(page_buff,x); WriteDat(Bef[2]-0x01); page_buff--; for(i=0;i<page_sub-1;i++) { OLED_SetPos(page_buff,x); WriteDat(0xff); page_buff--; } OLED_SetPos(page_buff,x); WriteDat(0xff<<Cur[1]); } else if(page_sub==0) { if(Cur[1]==Bef[1]) { OLED_SetPos(Cur[0],x); WriteDat(Cur[2]); } else if(Cur[1]>Bef[1]) { OLED_SetPos(Cur[0],x); WriteDat((Cur[2]-Bef[2])|Cur[2]); } else if(Cur[1]<Bef[1]) { OLED_SetPos(Cur[0],x); WriteDat(Bef[2]-Cur[2]); } } else if(page_sub<0) { page_buff=Cur[0]; OLED_SetPos(page_buff,x); WriteDat((Cur[2]<<1)-0x01); page_buff--; for(i=0;i<0-page_sub-1;i++) { OLED_SetPos(page_buff,x); WriteDat(0xff); page_buff--; } OLED_SetPos(page_buff,x); WriteDat(0xff<<(Bef[1]+1)); } Before_State_Update(y); //把下一列,每一页的数据清除掉 for(i=0;i<8;i++) { OLED_SetPos(i, x+1) ; for(j=0;j<1;j++) WriteDat(0x00); } } /* ********************************************************************************************************* * 函 数 名: OLED检测测试 * 功能说明: 检测I2C总线设备,实际是对OLED_CheckDevice()的封装 * 形 参: * 返 回 值: 返回值 0 表示没有检测到OLED,返回1表示检测到OLED ********************************************************************************************************* */ uint8_t OLED_Test(void) { if (OLED_CheckDevice(OLED_ADDRESS) == 1) { return 0; } else { return 1; } } /*写 缓存数据*/ void Write_DataBuffer(void)//这个是将DataBuffer数组里面的值,全部写进屏里去 { uint8_t i,j; for(i=0;i<8;i++) { OLED_SetPos(i,0); //设置起始点坐标 for(j=0;j<128;j++) { WriteDat(DataBuffer[i][j]);//写数据 } } }
#ifndef __OLED_I2C_H #define __OLED_I2C_H #include "stm32f10x.h" #define BUFF_SIZE 10 #define OLED_ADDRESS 0x78 //通过调整0R电阻,屏可以0x78和0x7A两个地址 -- 默认0x78 uint8_t OLED_CheckDevice(uint8_t _Address);//检测I2C总线设备OLED void I2C_WriteByte(uint8_t addr,uint8_t data); void WriteCmd(unsigned char I2C_Command); void WriteDat(unsigned char I2C_Data); void OLED_Init(void); void OLED_SetPos(unsigned char x, unsigned char y); void OLED_Fill(void); void OLED_CLS(void); void OLED_ON(void); void OLED_OFF(void); void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize); void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N); void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]); uint8_t OLED_Test(void) ;//OLED检测测试 void Write_DataBuffer(void); void OLED_DrawWave(uint8_t x,uint8_t y); void OLED_DrawPoint(uint8_t x,uint8_t y); void Before_State_Update(uint8_t y); #endif
#include "bsp_systick.h" #if 0 static __INLINE uint32_t SysTick_Config(uint32_t ticks) { if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */ SysTick->VAL = 0; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0); /* Function successful */ } #endif void Delay_ms(uint32_t ms) { uint32_t i; SysTick_Config(72000); /*配置为1ms中断一次*/ for(i=0;i<ms;i++) { while(!(SysTick->CTRL & (1<<16))); /*检测标志位(最高位)*/ } SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;/*关闭SysTick*/ } void Delay_us(uint32_t us) { uint32_t i; SysTick_Config(72); for(i=0;i<us;i++) { while(!(SysTick->CTRL & (1<<16))); } SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; }
#ifndef _BSP_SYSTICK_H
#define _BSP_SYSTICK_H
#include "stm32f10x.h"
#include "core_cm3.h"
void Delay_ms(uint32_t ms);
void Delay_us(uint32_t us);
#endif //_BSP_SYSTICK_H
#include "bsp_usart.h" void USARTx_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; USART_Rx_GPIO_CLK_CMD(USART_Rx_GPIO_CLK,ENABLE); USART_Tx_GPIO_CLK_CMD(USART_Tx_GPIO_CLK,ENABLE); GPIO_InitStruct.GPIO_Pin=USART_Rx_GPIO_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(USART_Rx_GPIO_PORT, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin=USART_Tx_GPIO_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(USART_Tx_GPIO_PORT, &GPIO_InitStruct); } void USARTx_Config(void) { USART_InitTypeDef USART_InitStruct; USARTx_CLK_CMD(USARTx_CLK,ENABLE); //初始化串口相关数据 USART_InitStruct.USART_BaudRate=USARTx_BAUD_RATE; USART_InitStruct.USART_WordLength=USART_WordLength_8b; USART_InitStruct.USART_StopBits=USART_StopBits_1; USART_InitStruct.USART_Parity=USART_Parity_No; USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx; USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; USART_Init(USARTx, &USART_InitStruct); //使能串口 USART_Cmd(USARTx, ENABLE); //使能串口中断 //USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE); } void USARTx_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStruct.NVIC_IRQChannel=USARTx_IRQCHANNEL; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStruct); } void USARTx_Init(void) { //USARTx_NVIC_Config(); USARTx_GPIO_Config(); USARTx_Config(); } int fputc(int ch,FILE* f) { USART_SendData(USARTx, (uint8_t)ch); while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)==RESET); return(ch); } int fgetc(FILE* f) { while(USART_GetFlagStatus(USARTx, USART_FLAG_RXNE)==RESET); return (int)USART_ReceiveData(USARTx); }
#ifndef _BSP_USART_H_ #define _BSP_USART_H_ #include "stm32f10x.h" #include <stdio.h> #define USARTx USART1 #define USARTx_BAUD_RATE 115200 #define USARTx_CLK RCC_APB2Periph_USART1 #define USARTx_CLK_CMD RCC_APB2PeriphClockCmd #define USARTx_IRQCHANNEL USART1_IRQn #define USARTx_IRQHANDLER USART1_IRQHandler #define USART_Rx_GPIO_PORT GPIOA #define USART_Rx_GPIO_PIN GPIO_Pin_10 #define USART_Rx_GPIO_CLK RCC_APB2Periph_GPIOA #define USART_Rx_GPIO_CLK_CMD RCC_APB2PeriphClockCmd #define USART_Tx_GPIO_PORT GPIOA #define USART_Tx_GPIO_PIN GPIO_Pin_9 #define USART_Tx_GPIO_CLK RCC_APB2Periph_GPIOA #define USART_Tx_GPIO_CLK_CMD RCC_APB2PeriphClockCmd void USARTx_GPIO_Config(void); void USARTx_Config(void); void USARTx_NVIC_Config(void); void USARTx_Init(void); #endif //_BSP_USART_H_
https://download.csdn.net/download/weixin_43599390/12667344
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。