打印
[应用相关]

使用STM32与labview设计的太阳能跟踪系统_原创作品

[复制链接]
楼主: wangjiahao88
手机看帖
扫描二维码
随时随地手机跟帖
21
wangjiahao88|  楼主 | 2018-11-4 12:45 | 只看该作者 回帖奖励 |倒序浏览
电机 读取反转

m4.png (33.25 KB )

m4.png

使用特权

评论回复
22
wangjiahao88|  楼主 | 2018-11-4 12:45 | 只看该作者
电机 读取风速

m4.png (33.25 KB )

m4.png

使用特权

评论回复
23
wangjiahao88|  楼主 | 2018-11-4 12:46 | 只看该作者
电机 读取拉力

m6.png (32.38 KB )

m6.png

使用特权

评论回复
24
wangjiahao88|  楼主 | 2018-11-4 12:46 | 只看该作者
电机 使能

m7.png (33.17 KB )

m7.png

使用特权

评论回复
25
wangjiahao88|  楼主 | 2018-11-4 12:46 | 只看该作者
电机 读取正转

m8.png (33.04 KB )

m8.png

使用特权

评论回复
26
wangjiahao88|  楼主 | 2018-11-4 12:47 | 只看该作者
子VI

10.png (217.47 KB )

10.png

使用特权

评论回复
27
wangjiahao88|  楼主 | 2018-11-4 12:50 | 只看该作者
LV工程压缩包

2017年8月21日.zip

3.55 MB

使用特权

评论回复
28
wangjiahao88|  楼主 | 2018-11-4 12:51 | 只看该作者
追光单片机程序工程目录1

追光1.png (154.32 KB )

追光1.png

使用特权

评论回复
29
wangjiahao88|  楼主 | 2018-11-4 12:52 | 只看该作者
main 函数:

#include "main.h"

int main(void)
{
    Get_ChipID();
    BASIC_TIM_Init();
    LED_GPIO_Config();
    Key_GPIO_Config();

    ADCx_Init();
    IIC_CfgGpio();
    MOTOR_GPIO_Config();
    MOTOR_TIM_Init();
    RC522_init();


    eMBInit(MB_RTU, 0x01, 1, 115200, MB_PAR_NONE);
    eMBEnable();

    while (1)
    {
        eMBPoll();//使能MODBUS
        MB_Sys_monitor();//MB_系统参数监控

        Get_filter_adc();//模拟量数据滤波
        YQ_Stateus=Get_Day_YQ();//鉴别是阴天还是晴天,0是阴天,1是晴天

        Rtc_read();//读取实时时钟
        LED_RUN_STATEUS();//读取实时时钟
        Read_RF_id();//试试获取RF卡的状态
        Test_new_RF_Card();//判断是不是获取到了一个新卡
        Get_Key_Xw();//获取输入与限位

        MB_Auto_Man_Ctrl();//PC、手动、自动控制

        Led_Error_Report();//LED显示与错误报告
        Amp_Error_Report();//电机电流故障检测
        Sensor_Error_Report();//传感器故障检测
        XW_Error_Report();//限位故障检测
    }
}

使用特权

评论回复
30
wangjiahao88|  楼主 | 2018-11-4 12:52 | 只看该作者
中断 定时器函数
/******************************************************************************/
/*                 STM32F10x Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f10x_xx.s).                                            */
/******************************************************************************/
void  BASIC_TIM_IRQHandler (void)
{
    static unsigned int T_1S_CNT;
    static unsigned int T_10ms_CNT;
    static unsigned int T_RTC_CNT;

    if(TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET )
    {
        T1_Count1++;
        T1_Count2++;
        T1_Count3++;

        //每100ms反转一次
        if(++T_RTC_CNT>99)
        {
            T_RTC_CNT=0;
            T_RTC_FLAG=!T_RTC_FLAG;
        }

        //每500ms反转一次
        if(++T_1S_CNT>499)
        {
            T_1S_CNT=0;
            T1S_FLAG=!T1S_FLAG;
        }

        //每50ms反转一次
        if(++T_10ms_CNT>49)
        {
            T_10ms_CNT=0;
            T100mS_FLAG=!T100mS_FLAG;
        }
        //每999ms反转一次
        if(++T1_Count3>999)
        {
            T1_Count3=0;
            T_1000ms_FLAG_calc=1;
        }
                               
        //每999ms反转一次
        if(++T1_Count4>999)
        {
            T1_Count4=0;
            T_1000ms_FLAG=1;
        }


        TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);
    }
}

使用特权

评论回复
31
wangjiahao88|  楼主 | 2018-11-4 12:52 | 只看该作者
变量表

#include "BLB.h"


uint32_t ChipUniqueID[3];

uint32_t T1_Count1 = 0; // ms 计时变量
uint32_t T1_Count2 = 0; // ms 计时变量
uint32_t T1_Count3 = 0; // ms 计时变量
uint32_t T1_Count4 = 0; // ms 计时变量

uint32_t T1S_FLAG = 0; // ms 计时变量
uint32_t T100mS_FLAG = 0;//ms 计时变量
uint32_t T_RTC_FLAG = 0;//ms 计时变量
uint32_t T_1000ms_FLAG = 0;//ms 计时变量
uint32_t T_1000ms_FLAG_calc = 0;//ms 计时变量

__IO uint16_t ADC_ConvertedValue[NOFCHANEL]= {0};
__IO uint16_t ADC_filter[NOFCHANEL]= {0};

__IO uint16_t T_Sensor_Shang=0;
__IO uint16_t T_Sensor_Xia=0;
__IO uint16_t T_Sensor_Dong=0;
__IO uint16_t T_Sensor_Xi=0;

__IO uint16_t B_Sensor_Shang=0;
__IO uint16_t B_Sensor_Xia=0;
__IO uint16_t B_Sensor_Dong=0;
__IO uint16_t B_Sensor_Xi=0;


unsigned char SW_AM=0;//手自动拨码开关

unsigned char Button_Dong=0;//按键东
unsigned char Button_Xi=0;//按键西
unsigned char Button_Shang=0;//按键上
unsigned char Button_Xia=0;//按键下

unsigned char XW_Dong=0;//限位东
unsigned char XW_Xi=0;//限位西
unsigned char XW_Shang=0;//限位上
unsigned char XW_Xia=0;//限位下

unsigned char RF_status=0;//卡状态标志
unsigned char RF_STEP=0; //卡类型
unsigned char RF_CT[2]; //卡类型
unsigned char RF_SN[4]; //卡号
unsigned char RF_Card_KEY[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };//卡密
unsigned int  RF_ADD=0;//地址
unsigned char RF_SEMI=0;//实时读取到的序列
unsigned char RF_SEMI_old=0;//旧序列
unsigned char RF_SEMI_change_flag=0;//序列改变的标志位

//方位与俯仰电机的状态;0:停止;1:顺转;2:逆转
unsigned char FW_M_Stateus=0;
unsigned char FY_M_Stateus=0;

//全自动跟踪的状态机
unsigned int SYS_STEP_Auto=0;
unsigned int SYS_STEP_Man=0;

//分钟改变的标志位
unsigned int Track_Calc_cnt_tmp=0;
unsigned int Track_Calc_start_stateus=0;

// 1 电流报警状态
unsigned int Amp_stateus=0;
// 2 传感器报警的状态
unsigned int Sensor_stateus=0;
// 3 限位报警的状态
unsigned int XW_stateus=0;

//阴晴状态
unsigned int YQ_Stateus=0;

//阴天自动运行的时间计数器与5分钟的状态标志
unsigned int A_track_cnt_tmp_Y=0;
unsigned int A_track_cnt_stateus=0;

//俯仰与方位的差值
int FY_Sensor_chazhi=0;
int FW_Sensor_chazhi=0;

使用特权

评论回复
32
wangjiahao88|  楼主 | 2018-11-4 12:53 | 只看该作者
ADC 模拟量

#include "bsp_adc.h"
#include "blb.h"


/**
  * @brief  ADC GPIO 初始化
  * @param  无
  * @retval 无
  */
static void ADCx_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    // 打开 ADC IO端口时钟
    ADC_GPIO_APBxClock_FUN ( ADC_Solar_CLK|
                             ADC_LaLi_CLK|
                             ADC_FS_CLK|
                             ADC_FW_Motor_CLK|
                             ADC_FY_Motor_CLK, ENABLE );

    // 配置Solar引脚模式
    GPIO_InitStructure.GPIO_Pin =           ADC_Solar_PIN1|
                                      ADC_Solar_PIN2|
                                      ADC_Solar_PIN3|
                                      ADC_Solar_PIN4|
                                      ADC_Solar_PIN5|
                                      ADC_Solar_PIN6|
                                      ADC_Solar_PIN7|
                                      ADC_Solar_PIN8;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    // 初始化 ADC IO
    GPIO_Init(ADC_Solar_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = ADC_LaLi_PIN1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(ADC_LaLi_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = ADC_FS_PIN1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(ADC_FS_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = ADC_FW_Motor_PIN1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(ADC_FW_Motor_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = ADC_FY_Motor_PIN1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(ADC_FY_Motor_PORT, &GPIO_InitStructure);

}

/**
  * @brief  配置ADC工作模式
  * @param  无
  * @retval 无
  */
static void ADCx_Mode_Config(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;

    // 打开DMA时钟
    RCC_AHBPeriphClockCmd(ADC_DMA_CLK, ENABLE);
    // 打开ADC时钟
    ADC_APBxClock_FUN ( ADC_CLK, ENABLE );

    // 复位DMA控制器
    DMA_DeInit(ADC_DMA_CHANNEL);

    // 配置 DMA 初始化结构体
    // 外设基址为:ADC 数据寄存器地址
    DMA_InitStructure.DMA_PeripheralBaseAddr = ( u32 ) ( & ( ADC_x->DR ) );

    // 存储器地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue;

    // 数据源来自外设
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

    // 缓冲区大小,应该等于数据目的地的大小
    DMA_InitStructure.DMA_BufferSize = NOFCHANEL;

    // 外设寄存器只有一个,地址不用递增
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

    // 存储器地址递增
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

    // 外设数据大小为半字,即两个字节
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

    // 内存数据大小也为半字,跟外设数据大小相同
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

    // 循环传输模式
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

    // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;

    // 禁止存储器到存储器模式,因为是从外设到存储器
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

    // 初始化DMA
    DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);

    // 使能 DMA 通道
    DMA_Cmd(ADC_DMA_CHANNEL , ENABLE);

    // ADC 模式配置
    // 只使用一个ADC,属于单模式
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

    // 扫描模式
    ADC_InitStructure.ADC_ScanConvMode = ENABLE ;

    // 连续转换模式
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

    // 不用外部触发转换,软件开启即可
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

    // 转换结果右对齐
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

    // 转换通道个数
    ADC_InitStructure.ADC_NbrOfChannel = NOFCHANEL;

    // 初始化ADC
    ADC_Init(ADC_x, &ADC_InitStructure);

    // 配置ADC时钟N狿CLK2的8分频,即9MHz
    RCC_ADCCLKConfig(RCC_PCLK2_Div8);

    // 配置ADC 通道的转换顺序和采样时间
    ADC_RegularChannelConfig(ADC_x, ADC_Solar_CHANNEL1, 1, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC_x, ADC_Solar_CHANNEL2, 2, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC_x, ADC_Solar_CHANNEL3, 3, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC_x, ADC_Solar_CHANNEL4, 4, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC_x, ADC_Solar_CHANNEL5, 5, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC_x, ADC_Solar_CHANNEL6, 6, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC_x, ADC_Solar_CHANNEL7, 7, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC_x, ADC_Solar_CHANNEL8, 8, ADC_SampleTime_55Cycles5);

    ADC_RegularChannelConfig(ADC_x, ADC_LaLi_CHANNEL1, 9, ADC_SampleTime_55Cycles5);

    ADC_RegularChannelConfig(ADC_x, ADC_FS_CHANNEL1, 10, ADC_SampleTime_55Cycles5);

    ADC_RegularChannelConfig(ADC_x, ADC_FW_Motor_CHANNEL1, 11, ADC_SampleTime_55Cycles5);

    ADC_RegularChannelConfig(ADC_x, ADC_FY_Motor_CHANNEL1, 12, ADC_SampleTime_55Cycles5);

    // 使能ADC DMA 请求
    ADC_DMACmd(ADC_x, ENABLE);

    // 开启ADC ,并开始转换
    ADC_Cmd(ADC_x, ENABLE);

    // 初始化ADC 校准寄存器
    ADC_ResetCalibration(ADC_x);
    // 等待校准寄存器初始化完成
    while(ADC_GetResetCalibrationStatus(ADC_x));

    // ADC开始校准
    ADC_StartCalibration(ADC_x);
    // 等待校准完成
    while(ADC_GetCalibrationStatus(ADC_x));

    // 由于没有采用外部触发,所以使用软件触发ADC转换
    ADC_SoftwareStartConvCmd(ADC_x, ENABLE);
}

/**
  * @brief  ADC初始化
  * @param  无
  * @retval 无
  */
void ADCx_Init(void)
{
    ADCx_GPIO_Config();
    ADCx_Mode_Config();
}

#define filter_len 5

unsigned int filter0(unsigned int data)
{
    static unsigned int buffer[filter_len] = {0};
    static unsigned int* buffer_p = (int*)buffer + (filter_len - 1);
    static unsigned int sum = (filter_len >> 1);
    sum -= *buffer_p;
    *buffer_p-- = data;
    sum += data;
    if (buffer_p < buffer)
    {
        buffer_p += filter_len;
    }
    return sum / filter_len;
}
unsigned int filter1(unsigned int data)
{
    static unsigned int buffer[filter_len] = {0};
    static unsigned int* buffer_p = (int*)buffer + (filter_len - 1);
    static unsigned int sum = (filter_len >> 1);
    sum -= *buffer_p;
    *buffer_p-- = data;
    sum += data;
    if (buffer_p < buffer)
    {
        buffer_p += filter_len;
    }
    return sum / filter_len;
}
unsigned int filter2(unsigned int data)
{
    static unsigned int buffer[filter_len] = {0};
    static unsigned int* buffer_p = (int*)buffer + (filter_len - 1);
    static unsigned int sum = (filter_len >> 1);
    sum -= *buffer_p;
    *buffer_p-- = data;
    sum += data;
    if (buffer_p < buffer)
    {
        buffer_p += filter_len;
    }
    return sum / filter_len;
}
unsigned int filter3(unsigned int data)
{
    static unsigned int buffer[filter_len] = {0};
    static unsigned int* buffer_p = (int*)buffer + (filter_len - 1);
    static unsigned int sum = (filter_len >> 1);
    sum -= *buffer_p;
    *buffer_p-- = data;
    sum += data;
    if (buffer_p < buffer)
    {
        buffer_p += filter_len;
    }
    return sum / filter_len;
}
unsigned int filter4(unsigned int data)
{
    static unsigned int buffer[filter_len] = {0};
    static unsigned int* buffer_p = (int*)buffer + (filter_len - 1);
    static unsigned int sum = (filter_len >> 1);
    sum -= *buffer_p;
    *buffer_p-- = data;
    sum += data;
    if (buffer_p < buffer)
    {
        buffer_p += filter_len;
    }
    return sum / filter_len;
}
unsigned int filter5(unsigned int data)
{
    static unsigned int buffer[filter_len] = {0};
    static unsigned int* buffer_p = (int*)buffer + (filter_len - 1);
    static unsigned int sum = (filter_len >> 1);
    sum -= *buffer_p;
    *buffer_p-- = data;
    sum += data;
    if (buffer_p < buffer)
    {
        buffer_p += filter_len;
    }
    return sum / filter_len;
}
unsigned int filter6(unsigned int data)
{
    static unsigned int buffer[filter_len] = {0};
    static unsigned int* buffer_p = (int*)buffer + (filter_len - 1);
    static unsigned int sum = (filter_len >> 1);
    sum -= *buffer_p;
    *buffer_p-- = data;
    sum += data;
    if (buffer_p < buffer)
    {
        buffer_p += filter_len;
    }
    return sum / filter_len;
}
unsigned int filter7(unsigned int data)
{
    static unsigned int buffer[filter_len] = {0};
    static unsigned int* buffer_p = (int*)buffer + (filter_len - 1);
    static unsigned int sum = (filter_len >> 1);
    sum -= *buffer_p;
    *buffer_p-- = data;
    sum += data;
    if (buffer_p < buffer)
    {
        buffer_p += filter_len;
    }
    return sum / filter_len;
}

void Get_filter_adc(void)
{
    if(T100mS_FLAG)
    {
        ADC_filter[0]=filter0(ADC_ConvertedValue[0]);
        ADC_filter[1]=filter1(ADC_ConvertedValue[1]);
        ADC_filter[2]=filter2(ADC_ConvertedValue[2]);
        ADC_filter[3]=filter3(ADC_ConvertedValue[3]);
        ADC_filter[4]=filter4(ADC_ConvertedValue[4]);
        ADC_filter[5]=filter5(ADC_ConvertedValue[5]);
        ADC_filter[6]=filter6(ADC_ConvertedValue[6]);
        ADC_filter[7]=filter7(ADC_ConvertedValue[7]);


        //将模拟量赋值给上、下、东、西四个方向的光电传感器,顶层
        T_Sensor_Shang=ADC_filter[1];
        T_Sensor_Xia=ADC_filter[0];
        T_Sensor_Dong=ADC_filter[2];
        T_Sensor_Xi=ADC_filter[3];

        //将模拟量赋值给上、下、东、西四个方向的光电传感器,底层
        B_Sensor_Shang=ADC_filter[4];
        B_Sensor_Xia=ADC_filter[5];
        B_Sensor_Dong=ADC_filter[7];
        B_Sensor_Xi=ADC_filter[6];

        FW_Sensor_chazhi=B_Sensor_Dong-B_Sensor_Xi;
        FY_Sensor_chazhi=B_Sensor_Shang-B_Sensor_Xia;
    }
}

//获取最大值,判断阴天晴天
//阴天,返回0
//晴天,返回1
unsigned char Get_Day_YQ(void)
{
    if((T_Sensor_Shang+T_Sensor_Xia+T_Sensor_Dong+T_Sensor_Xi)>Sensor_YQ)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
/*********************************************END OF FILE**********************/

使用特权

评论回复
33
wangjiahao88|  楼主 | 2018-11-4 12:53 | 只看该作者
串口

#include "bsp_usart.h"

/**
* @brief  配置嵌套向量中断控制器NVIC
* @param  无
* @retval 无
*/
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);
}

/**
* @brief  USART GPIO 配置,工作参数配置
* @param  无
* @retval 无
*/
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 ch)
{
    /* 发送一个字节数据到USART */
    USART_SendData(pUSARTx,ch);

    /* 等待发送数据寄存器为空 */
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}

/****************** 发送8位的数组 ************************/
void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
{
    uint8_t i;

    for(i=0; i<num; i++)
    {
        /* 发送一个字节数据到USART */
        Usart_SendByte(pUSARTx,array[i]);

    }
    /* 等待发送完成 */
    while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}

/*****************  发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
    unsigned int k=0;
    do
    {
        Usart_SendByte( pUSARTx, *(str + k) );
        k++;
    } while(*(str + k)!='\0');

    /* 等待发送完成 */
    while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
    {}
}

/*****************  发送一个16位数 **********************/
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{
    uint8_t temp_h, temp_l;

    /* 取出高八位 */
    temp_h = (ch&0XFF00)>>8;
    /* 取出低八位 */
    temp_l = ch&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);
}

///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    /* 发送一个字节数据到串口 */
    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);
}

使用特权

评论回复
34
wangjiahao88|  楼主 | 2018-11-4 12:53 | 只看该作者
LED
#include "main.h"

/**
* @brief  初始化控制LED的IO
* @param  无
* @retval 无
*/
void LED_GPIO_Config(void)
{
    /*定义一个GPIO_InitTypeDef类型的结构体*/
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);  //开启AFIO时钟
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE); //禁止JTAG功能

    /*开启LED相关的GPIO外设时钟*/
    RCC_APB2PeriphClockCmd(
        LED1_GPIO_CLK |
        LED2_GPIO_CLK |
        LED3_GPIO_CLK |
        LED4_GPIO_CLK |
        LED5_GPIO_CLK |
        LED6_GPIO_CLK |
        LED7_GPIO_CLK |
        LED8_GPIO_CLK |
        LED_RUN_GPIO_CLK,ENABLE);

    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;

    /*设置引脚模式为通用推挽输出*/
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    /*设置引脚速率为50MHz */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    /*调用库函数,初始化GPIO*/
    GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;
    /*调用库函数,初始化GPIO*/
    GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED3_GPIO_PIN;
    /*调用库函数,初始化GPIOF*/
    GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED4_GPIO_PIN;
    /*调用库函数,初始化GPIOF*/
    GPIO_Init(LED4_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED5_GPIO_PIN;
    /*调用库函数,初始化GPIOF*/
    GPIO_Init(LED5_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED6_GPIO_PIN;
    /*调用库函数,初始化GPIOF*/
    GPIO_Init(LED6_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED7_GPIO_PIN;
    /*调用库函数,初始化GPIOF*/
    GPIO_Init(LED7_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED8_GPIO_PIN;
    /*调用库函数,初始化GPIOF*/
    GPIO_Init(LED8_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的GPIO引脚*/
    GPIO_InitStructure.GPIO_Pin = LED_RUN_GPIO_PIN;
    /*调用库函数,初始化GPIOF*/
    GPIO_Init(LED_RUN_GPIO_PORT, &GPIO_InitStructure);

    /* 关闭所有led灯        */
    GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
    GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN);
    GPIO_SetBits(LED3_GPIO_PORT, LED3_GPIO_PIN);
    GPIO_SetBits(LED4_GPIO_PORT, LED4_GPIO_PIN);
    GPIO_SetBits(LED5_GPIO_PORT, LED5_GPIO_PIN);
    GPIO_SetBits(LED6_GPIO_PORT, LED6_GPIO_PIN);
    GPIO_SetBits(LED7_GPIO_PORT, LED7_GPIO_PIN);
    GPIO_SetBits(LED8_GPIO_PORT, LED8_GPIO_PIN);
    GPIO_SetBits(LED_RUN_GPIO_PORT, LED_RUN_GPIO_PIN);
}


void Led_welcome(void)
{
    LED5(ON);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED6(ON);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED7(ON);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED8(ON);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED5(OFF);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED6(OFF);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED7(OFF);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED8(OFF);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED5(ON);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED6(ON);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED7(ON);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED8(ON);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED5(OFF);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED6(OFF);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED7(OFF);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
    LED8(OFF);
    for(int LOOP_cnt=0; LOOP_cnt<0xfffff; LOOP_cnt++);
}

/*********************************************END OF FILE**********************/

使用特权

评论回复
35
wangjiahao88|  楼主 | 2018-11-4 12:54 | 只看该作者
按键

/**
  ******************************************************************************
  * @file    bsp_key.c
  * @author  fire
  * @version V1.0
  * @date    2013-xx-xx
  * @brief   按键应用bsp(扫描模式)
  ******************************************************************************
  * @attention
  *
  * 实验平台:秉火 F103-霸道 STM32 开发板
  * 论坛    :http://www.firebbs.cn
  * 淘宝    :https://fire-stm32.taobao.com
  *
  ******************************************************************************
  */

#include "main.h"

/**
  * @brief  配置按键用到的I/O口
  * @param  无
  * @retval 无
  */
void Key_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /*开启按键端口的时钟*/
    RCC_APB2PeriphClockCmd(
        SWITCH_AM_CLK|
        KEY_FW_D_CLK|
        KEY_FW_X_CLK|
        KEY_FY_S_CLK|
        KEY_FY_X_CLK|
        XW_FW_D_CLK |
        XW_FW_X_CLK |
        XW_FY_S_CLK |
        XW_FY_X_CLK,ENABLE);

    //选择按键的引脚
    GPIO_InitStructure.GPIO_Pin = SWITCH_AM_PIN;
    // 设置按键的引脚为浮空输入
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    //使用结构体初始化按键
    GPIO_Init(SWITCH_AM_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = KEY_FW_D_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(KEY_FW_D_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = KEY_FW_X_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(KEY_FW_X_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = KEY_FY_S_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(KEY_FY_S_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = KEY_FY_X_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(KEY_FY_X_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = XW_FW_D_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(XW_FW_D_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = XW_FW_X_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(XW_FW_X_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = XW_FY_S_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(XW_FY_S_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = XW_FY_X_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(XW_FY_X_PORT, &GPIO_InitStructure);

}

/*
* 函数名:Key_Scan
* 描述  :检测是否有按键按下
* 输入  :GPIOx:x 可以是 A,B,C,D或者 E
*                      GPIO_Pin:待读取的端口位
* 输出  :KEY_OFF(没按下按键)、KEY_ON(按下按键)
*/
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{
    /*检测是否有按键按下 */
    if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON )
    {
        return         KEY_ON;
    }
    else
        return KEY_OFF;
}
/*********************************************END OF FILE**********************/
void Get_Key_Xw(void)
{
    //获取手自动开关、限位的状态
    SW_AM       =Key_Scan(SWITCH_AM_PORT,SWITCH_AM_PIN);
    Button_Dong =Key_Scan(KEY_FW_D_PORT,KEY_FW_D_PIN);
    Button_Xi   =Key_Scan(KEY_FW_X_PORT,KEY_FW_X_PIN);
    Button_Shang=Key_Scan(KEY_FY_S_PORT,KEY_FY_S_PIN);
    Button_Xia  =Key_Scan(KEY_FY_X_PORT,KEY_FY_X_PIN);
    XW_Dong     =Key_Scan(XW_FW_D_PORT,XW_FW_D_PIN);
    XW_Xi       =Key_Scan(XW_FW_X_PORT,XW_FW_X_PIN);
    XW_Shang    =Key_Scan(XW_FY_S_PORT,XW_FY_S_PIN);
    XW_Xia      =Key_Scan(XW_FY_X_PORT,XW_FY_X_PIN);

    //LED与限位
    LED1(!XW_Dong);
    LED2(!XW_Xi);
    LED3(!XW_Shang);
    LED4(!XW_Xia);

    //按下了一个按键之后,解除掉MODBUS控制
    if(Button_Dong||Button_Xi||Button_Shang||Button_Xia)usSRegHoldBuf[100]=0;

}

使用特权

评论回复
36
wangjiahao88|  楼主 | 2018-11-4 12:54 | 只看该作者
#include "bsp_delay.h"

// 软件延时
void Delay(__IO uint32_t nCount)
{
    for(; nCount != 0; nCount--);
}


延时

使用特权

评论回复
37
wangjiahao88|  楼主 | 2018-11-4 12:54 | 只看该作者
定时器


// 基本定时器TIMx,x[6,7]定时初始化函数

#include "bsp_TiMbase.h"

// 中断优先级配置
static void BASIC_TIM_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    // 设置中断组为0
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);               
                // 设置中断来源
    NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQ ;       
                // 设置主优先级为 0
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;         
          // 设置抢占优先级为3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;       
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/*
* 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
* TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
* 另外三个成员是通用定时器和高级定时器才有.
*-----------------------------------------------------------------------------
*typedef struct
*{ TIM_Prescaler            都有
*        TIM_CounterMode                             TIMx,x[6,7]没有,其他都有
*  TIM_Period               都有
*  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有
*  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
*}TIM_TimeBaseInitTypeDef;
*-----------------------------------------------------------------------------
*/


static void BASIC_TIM_Mode_Config(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
               
                // 开启定时器时钟,即内部时钟CK_INT=72M
    BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);
       
                // 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
    TIM_TimeBaseStructure.TIM_Period = BASIC_TIM_Period;       

          // 时钟预分频数为
    TIM_TimeBaseStructure.TIM_Prescaler= BASIC_TIM_Prescaler;
       
                // 时钟分频因子 ,基本定时器没有,不用管
    //TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
               
                // 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
    //TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
               
                // 重复计数器的值,基本定时器没有,不用管
                //TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
       
          // 初始化定时器
    TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);
               
                // 清除计数器中断标志位
    TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
          
                // 开启计数器中断
    TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
               
                // 使能计数器
    TIM_Cmd(BASIC_TIM, ENABLE);       
}

void BASIC_TIM_Init(void)
{
        BASIC_TIM_NVIC_Config();
        BASIC_TIM_Mode_Config();
}
/*********************************************END OF FILE**********************/

使用特权

评论回复
38
wangjiahao88|  楼主 | 2018-11-4 12:54 | 只看该作者
IIC

#include "bsp_i2c_ee.h"
#include "bsp_i2c_gpio.h"
#include "bsp_usart.h"

/******************************************************************
- 功能描述:向AT24C64的地址为addr的单元上写入一个字节dat
- 隶属模块:AT24C64模块
- 函数属性:外部,供用户使用
- 参数说明:addr:AT24C64的单元地址
             dat:要写入的字节
- 返回说明:无
- 注:AT24C64的地址是字节级地址,即最小存储单元是字节,地址范围
       是0~8191
******************************************************************/

void AT24C64_Write_Byte(unsigned char device_add,unsigned int addr,unsigned char dat)
{
    IIC_Start(); //启动IIC传输
    IIC_Write_Byte(device_add); //1010 A2 A1 A0 R/W [A2:A0]是AT24C64的芯片地址,0~7,即同一条IIC总线上可以挂接8个芯片;R/W是读/写选择位,0为写操作,1为读操作
    IIC_Write_Byte(addr>>8);//写入地址高字节
    IIC_Write_Byte(addr); //写入地址低字节
    IIC_Write_Byte(dat); //写入一个字节的数据
    IIC_Stop(); //IIC传输结束,AT24C64开始执行,即将这一个字节写入EEPROM中

    IIC_Delay(10000); //等待AT24C64操作完成,最大5ms
    IIC_Delay(10000); //等待AT24C64操作完成,最大5ms
}

/******************************************************************
- 功能描述:写页操作
- 隶属模块:AT24C64模块
- 函数属性:外部,供用户使用
- 参数说明:addr:页开始地址
             pbuf:指向数据缓冲区的指针
- 返回说明:无
- 注:向AT24C64芯片addr地址后面连续写入32个字节,即写页操作,
       这些数据存放在pbuf中
******************************************************************/

void AT24C64_Write_Page(unsigned char device_add,unsigned int addr,unsigned char *pbuf)
{
    unsigned char i;
    IIC_Start(); //启动IIC传输
    IIC_Write_Byte(device_add); //1010 A2 A1 A0 R/W [A2:A0]是AT24C64的芯片地址,0~7,即同一条IIC总线上可以挂接8个芯片;R/W是读/写选择位,0为写操作,1为读操作
    IIC_Write_Byte(addr>>8);//写入地址高字节
    IIC_Write_Byte(addr); //写入地址低字节
    for(i=0; i<32; i++)
    {
        IIC_Write_Byte(pbuf[i]); //将pbuf中的32个字节写入AT24C64的数据缓冲区
    }
    IIC_Stop(); //IIC传输结束,AT24C64开始执行,即将这32个字节写入EEPROM中

    IIC_Delay(10000); //等待AT24C64操作完成,最大5ms
    IIC_Delay(10000); //等待AT24C64操作完成,最大5ms
}

/******************************************************************
- 功能描述:从当前地址连续读取length个字节,放入pbuf指向的数据缓冲区
- 隶属模块:AT24C64模块
- 函数属性:外部,供用户使用
- 参数说明:length:要读取的数据长度
             pbuf:指向数据缓冲区的指针
- 返回说明:无
- 注:从当前的地址上读取数据,所以此函数中没有写入地址的操作
******************************************************************/

void AT24C64_Current_Addr_Read(unsigned char device_add,unsigned int length,unsigned char *pbuf)
{
    unsigned char i;
    IIC_Start(); //启动传输,这里再次启动传输,因为下面要写入“读操作”的指令码,即0xa1
    IIC_Write_Byte(device_add+1); //写入0xa1,从AT24C64中读取数据
    for(i=0; i<length-1; i++)
    {
        pbuf[i]=IIC_Read_Byte(); //读取length-1个字节
        IIC_Ack();                           //前length-1个字节,每读完一个字节要向AT24C64提供ACK,即告诉其继续提供下面的数据,读取操作还未完毕
    }
    pbuf[i]=IIC_Read_Byte(); //读取最后一个字节,即第length个字节
    IIC_NAck();   //读取最后一个字节后,要向AT24C64提NACK,告诉其读取操作结束,不再向下读了
    IIC_Stop(); //传输结束
}

/******************************************************************
- 功能描述:从某个地址读取一个字节
- 隶属模块:AT24C64模块
- 函数属性:外部,供用户使用
- 参数说明:addr:要读取字节的地址
- 返回说明:读到的字节
- 注:此函数中直接调用了上面的        AT24C64_Current_Addr_Read函数
       只是在它前面进行了地址的写入
******************************************************************/

unsigned char AT24C64_Read_Byte(unsigned char device_add,unsigned int addr)
{
    unsigned char temp;

    IIC_Start(); //启动传输
    IIC_Write_Byte(device_add);
    IIC_Write_Byte(addr>>8); //写入地址高字节
    IIC_Write_Byte(addr); //写入地址低字节

    AT24C64_Current_Addr_Read(device_add,1,&temp); //从当前地址读取一个字节,放入temp中
    return temp;//返回temp的值,即读到的字节
}

/******************************************************************
- 功能描述:连续读操作
- 隶属模块:AT24C64模块
- 函数属性:外部,供用户使用
- 参数说明:addr:要读取的开始地址
             length:要读取的数据长度
             pbuf:指向数据缓冲区的指针
- 返回说明:无
- 注:从addr地址连续读取length个字节到pbuf中
******************************************************************/

void AT24C64_Sequential_Read(unsigned char device_add,unsigned int addr,unsigned int length,unsigned char *pbuf)
{
    IIC_Start(); //启动传输
    IIC_Write_Byte(device_add);
    IIC_Write_Byte(addr>>8); //写入地址高字节
    IIC_Write_Byte(addr); //写入地址低字节

    AT24C64_Current_Addr_Read(device_add,length,pbuf); //从当前地址读取32个字节,放入pbuf中
}

使用特权

评论回复
39
wangjiahao88|  楼主 | 2018-11-4 12:54 | 只看该作者
IIC GPIO

#include "stm32f10x.h"
#include "./i2c/bsp_i2c_gpio.h"


/*
*********************************************************************************************************
*        函 数 名: i2c_CfgGpio
*        功能说明: 配置I2C总线的GPIO,采用模拟IO的方式实现
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
void IIC_CfgGpio(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(EEPROM_RCC_I2C_PORT, ENABLE);        /* 打开GPIO时钟 */

    GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SCL_PIN | EEPROM_I2C_SDA_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;          /* 开漏输出 */
    GPIO_Init(EEPROM_GPIO_PORT_I2C, &GPIO_InitStructure);

    /* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
    IIC_Stop();
}

/*
*********************************************************************************************************
*        函 数 名: i2c_Delay
*        功能说明: I2C总线位延迟,最快400KHz
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
void IIC_Delay(unsigned int count)
{
    unsigned int i;
    for (i = 0; i < count; i++);
}

/*
*********************************************************************************************************
*        函 数 名: i2c_Start
*        功能说明: CPU发起I2C总线启动信号
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
void IIC_Start(void)
{
    /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
    EEPROM_I2C_SDA_1();
    IIC_Delay(5);
    EEPROM_I2C_SCL_1();
    IIC_Delay(50);
    EEPROM_I2C_SDA_0();
    IIC_Delay(50);
    EEPROM_I2C_SCL_0();
    IIC_Delay(5);
}

/*
*********************************************************************************************************
*        函 数 名: i2c_Start
*        功能说明: CPU发起I2C总线停止信号
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
void IIC_Stop(void)
{
    /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
    EEPROM_I2C_SDA_0();
    IIC_Delay(5);
    EEPROM_I2C_SCL_1();
    IIC_Delay(50);
    EEPROM_I2C_SDA_1();
    IIC_Delay(50);
}

/*
*********************************************************************************************************
*        函 数 名: i2c_Ack
*        功能说明: CPU产生一个ACK信号
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
void IIC_Ack(void)
{
    EEPROM_I2C_SDA_0();        /* CPU驱动SDA = 0 */
    IIC_Delay(5);
    EEPROM_I2C_SCL_1();        /* CPU产生1个时钟 */
    IIC_Delay(50);
    EEPROM_I2C_SCL_0();
    IIC_Delay(5);
}

/*
*********************************************************************************************************
*        函 数 名: i2c_NAck
*        功能说明: CPU产生1个NACK信号
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
void IIC_NAck(void)
{
    EEPROM_I2C_SDA_1();        /* CPU驱动SDA = 1 */
    IIC_Delay(5);
    EEPROM_I2C_SCL_1();        /* CPU产生1个时钟 */
    IIC_Delay(50);
    EEPROM_I2C_SCL_0();
    IIC_Delay(5);
}
/*
*********************************************************************************************************
*        函 数 名: i2c_WaitAck
*        功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
*        形    参:无
*        返 回 值: 返回0表示正确应答,1表示无器件响应
*********************************************************************************************************
*/
unsigned char IIC_Get_Ack(void)
{
    unsigned char Error;

    EEPROM_I2C_SDA_1();        /* CPU释放SDA总线 */
    IIC_Delay(5);
    EEPROM_I2C_SCL_1();        /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
    IIC_Delay(50);
    if (EEPROM_I2C_SDA_READ())        /* CPU读取SDA口线状态 */
    {
        Error = 1;
    }
    else
    {
        Error = 0;
    }
    EEPROM_I2C_SCL_0();
    IIC_Delay(50);
    return Error;
}

/*
*********************************************************************************************************
*        函 数 名: i2c_SendByte
*        功能说明: CPU向I2C总线设备发送8bit数据
*        形    参:_ucByte : 等待发送的字节
*        返 回 值: 无
*********************************************************************************************************
*/
unsigned char IIC_Write_Byte(unsigned char dat)
{
    unsigned char i;

    /* 先发送字节的高位bit7 */
    for (i = 0; i < 8; i++)
    {
        if ((dat<<i) & 0x80)
        {
            EEPROM_I2C_SDA_1();
        }
        else
        {
            EEPROM_I2C_SDA_0();
        }
        IIC_Delay(5);
        EEPROM_I2C_SCL_1();
        IIC_Delay(50);
        EEPROM_I2C_SCL_0();
        IIC_Delay(5);
    }
    return IIC_Get_Ack();
}

/*
*********************************************************************************************************
*        函 数 名: i2c_ReadByte
*        功能说明: CPU从I2C总线设备读取8bit数据
*        形    参:无
*        返 回 值: 读到的数据
*********************************************************************************************************
*/
unsigned char IIC_Read_Byte(void)
{
    unsigned char i,rbyte=0;

    EEPROM_I2C_SDA_1();

    for (i = 0; i < 8; i++)
    {
        EEPROM_I2C_SCL_1();
        IIC_Delay(50);
        if (EEPROM_I2C_SDA_READ())
        {
            rbyte|=(0x80>>i);
        }
        EEPROM_I2C_SCL_0();
        IIC_Delay(5);
    }
    return rbyte;
}

使用特权

评论回复
40
wangjiahao88|  楼主 | 2018-11-4 12:55 | 只看该作者
PCF 8563

#include "bsp_pcf8563.h"
#include "./i2c/bsp_i2c_gpio.h"

volatile Time rtc; //用来装时间数据,需要在外部定义

/******************************************************************
- 功能描述:向地址addr的寄存器写入多个字节
- 隶属模块:PCF8563驱动模块
- 函数属性:内部
- 参数说明:addr:寄存器地址
             length:要写入的字节数
             pbuf:指向数据缓冲区的指针           
- 返回说明:操作结果,0表示成功,1表示失败
- 注:无
******************************************************************/

unsigned char PCF8563_Write_Bytes(unsigned char addr,unsigned char length,unsigned char *pbuf)
{
unsigned char i=0;
IIC_Start(); //IIC通信开始
if(IIC_Write_Byte(0xa2)) return 1; //写PCF8563的ID与读写控制位,通信有错误立即返回
if(IIC_Write_Byte(addr)) return 1; //写寄存器地址
for(i=0;i<length;i++) //写入length个字节
{
  if(IIC_Write_Byte(pbuf[i])) return 1;//写数据
}
IIC_Stop();
return 0;
}
/******************************************************************
- 功能描述:从地址addr的寄存器读取多个字节
- 隶属模块:PCF8563驱动模块
- 函数属性:内部
- 参数说明:addr:寄存器地址
             length:要读出的字节数
             pbuf:指向数据缓冲区的指针           
- 返回说明:操作结果,0表示成功,1表示失败
- 注:无
******************************************************************/

unsigned char PCF8563_Read_Bytes(unsigned char addr,unsigned char length,unsigned char *pbuf) //从地址addr连续读取length个字节到pbuf
{
unsigned char i=0,err=0;
IIC_Start(); //IIC通信开始
if(IIC_Write_Byte(0xa2)) return 1; //写PCF8563的ID与读写控制位,通信有错误立即返回
if(IIC_Write_Byte(addr)) return 1; //写寄存器地址

IIC_Start(); //IIC通信开始
if(IIC_Write_Byte(0xa3)) return 1; //写PCF8563的ID与读写控制位
for(i=0;i<length-1;i++) //写入前length-1个字节,并作出应答
{
  pbuf[i]=IIC_Read_Byte();
  IIC_Ack();
}
pbuf[i]=IIC_Read_Byte(); //写入最后一个字节,并作出无应答
IIC_NAck();
IIC_Stop();
return 0;
}

/******************************************************************
- 功能描述:将BCD码转换为十进制的数值
- 隶属模块:PCF8563驱动模块
- 函数属性:内部
- 参数说明:x:待转换的BCD码字节         
- 返回说明:转换后的值
- 注:将BCD格式数据转为实际的值,如29的BCD格式为0x29,实际值为0x1d
******************************************************************/

unsigned char BCD2Val(unsigned char x)
{
return (x>>4)*10+(x&0x0f); //高4位乘以10,再加上低4位,即得到数值
}
/******************************************************************
- 功能描述:将十进制的数值转换为BCD码
- 隶属模块:PCF8563驱动模块
- 函数属性:内部
- 参数说明:x:待转换的数值         
- 返回说明:转换后的值
- 注:将值转为BCD格式,如 23转为BCD格式为 0x23
******************************************************************/

unsigned char Val2BCD(unsigned char x)
{
return (x/10)*16+(x%10); //将十进制的数值十位乘以16,再加上个位,即得到BCD码
}
/******************************************************************
- 功能描述:读取时间
- 隶属模块:PCF8563驱动模块
- 函数属性:外部,供用户使用
- 参数说明:无        
- 返回说明:操作结果,0表示成功,1表示失败
- 注:从PCF8563中读到的时间值,被装载到全局的外部结构体变量time中
******************************************************************/

unsigned char P8563_Read_Time()
{
unsigned char temp[7];
if(!PCF8563_Read_Bytes(0x02,7,temp)) //读取时间,即读取PCF8563的时间寄存器,地址从0x02开始
{
  //以下对读取到temp数组中的时间数据进行截取
  //并转换为十进制数值写入到time中去
  rtc.second=BCD2Val(temp[0]&0x7f); //秒
  rtc.minute=BCD2Val(temp[1]&0x7f); //分
  rtc.hour  =BCD2Val(temp[2]&0x3f); //小时
  rtc.day   =BCD2Val(temp[3]&0x3f); //日
  rtc.week  =BCD2Val(temp[4]&0x07); //星期
  rtc.month =BCD2Val(temp[5]&0x1f); //月
  rtc.year  =BCD2Val(temp[6]     ); //年
  return 0;
}
else
return 1;
}
/******************************************************************
- 功能描述:设置时间
- 隶属模块:PCF8563驱动模块
- 函数属性:外部,供用户使用
- 参数说明:无        
- 返回说明:操作结果,0表示成功,1表示失败
- 注:在设置时间前先将时间数据填充到time中去,随后调用此函数,时间
       数据即被写入到PCF8563中,并以新设置的时间继续走时
******************************************************************/

unsigned char P8563_Set_Time()
{
unsigned char temp[7];
unsigned char i;
for(i=0;i<7;i++)
{
  temp[i]=Val2BCD(((unsigned char *)(&rtc))[i]);//将time中的时间数据转换为BCD格式,并写入到temp数组中
}
return PCF8563_Write_Bytes(0x02,7,temp); //将temp数组的数据写入到PCF8563中
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则