初始化仓库
This commit is contained in:
91
Source/PCA9685_driver.c
Normal file
91
Source/PCA9685_driver.c
Normal file
@@ -0,0 +1,91 @@
|
||||
#include "PCA9685_driver.h"
|
||||
#include "delay.h"
|
||||
|
||||
#if PCA9685_USE_SOFT_IIC == 1
|
||||
#include "iic_soft.h"
|
||||
static IIC_Soft_Config config;
|
||||
#else
|
||||
#include "iic.h"
|
||||
#endif
|
||||
|
||||
static uint8 has_init = 0;
|
||||
|
||||
void pca9685_init()
|
||||
{
|
||||
if(has_init) return; // 如果已经初始化过,则直接返回
|
||||
#if PCA9685_USE_SOFT_IIC == 1
|
||||
config.scl_pin = PCA9685_SOFT_IIC_SCL_PIN;
|
||||
config.sda_pin = PCA9685_SOFT_IIC_SDA_PIN;
|
||||
config.wait_time = 10;
|
||||
soft_iic_init(&config); // 初始化软件IIC
|
||||
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, PCA9685_MODE1, 0x00); // 设置PCA9685模式寄存器为正常模式
|
||||
#else
|
||||
// 初始化I2C接口
|
||||
iic_init(IIC_1, 20);
|
||||
iic_write_reg(PCA9685_I2C_ADDR, PCA9685_MODE1, 0x00); // 设置为正常模式
|
||||
#endif
|
||||
|
||||
pca9685_set_frequency(PCA9685_DEF_FREQ); // 设置默认频率
|
||||
has_init = 1;
|
||||
}
|
||||
|
||||
void pca9685_deinit()
|
||||
{
|
||||
if(!has_init) return; // 如果没有初始化过,则直接返回
|
||||
has_init = 0; // 标记为未初始化
|
||||
}
|
||||
|
||||
void pca9685_set_frequency(uint16 frequency)
|
||||
{
|
||||
// 计算预分频器值
|
||||
uint8 prescale = 0;
|
||||
uint8 old_mode1 = 0;
|
||||
double prescale_value = 0.0;
|
||||
prescale_value = 6103.515625 / frequency;
|
||||
if (prescale_value < 3.0) {
|
||||
prescale = 3; // 最小预分频器值
|
||||
} else if (prescale_value > 255.0) {
|
||||
prescale = 255; // 最大预分频器值
|
||||
} else {
|
||||
prescale = (uint8)prescale_value; // 正常预分频器值
|
||||
if (prescale_value - prescale >= 0.5) {
|
||||
prescale += 1; // 四舍五入
|
||||
}
|
||||
}
|
||||
#if PCA9685_USE_SOFT_IIC == 1
|
||||
// soft_iic_read_reg(&config, PCA9685_I2C_ADDR, PCA9685_MODE1, &old_mode1); // 读取当前模式寄存器
|
||||
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, PCA9685_MODE1, (old_mode1 & 0x7F) | 0x10); // 进入睡眠模式
|
||||
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, PCA9685_PRESCALE, prescale); // 设置预分频器
|
||||
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, PCA9685_MODE1, old_mode1); // 恢复正常模式
|
||||
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, PCA9685_MODE1, old_mode1 | 0x80); // 重启PCA9685
|
||||
#else
|
||||
// P05 = 0;
|
||||
// 设置预分频器
|
||||
// iic_read_reg(PCA9685_I2C_ADDR, PCA9685_MODE1, &old_mode1);
|
||||
iic_write_reg(PCA9685_I2C_ADDR, PCA9685_MODE1, (old_mode1 & 0x7F) | 0x10); // 进入睡眠模式
|
||||
iic_write_reg(PCA9685_I2C_ADDR, PCA9685_PRESCALE, prescale);
|
||||
// 恢复模式寄存器
|
||||
iic_write_reg(PCA9685_I2C_ADDR, PCA9685_MODE1, old_mode1); // 恢复正常模式
|
||||
delay_ms(5); // 等待模式寄存器更新
|
||||
iic_write_reg(PCA9685_I2C_ADDR, PCA9685_MODE1, old_mode1 | 0x80); // 重启PCA9685
|
||||
// P05 = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void pca9685_set_pwm(uint8 channel, uint16 on, uint16 off)
|
||||
{
|
||||
// P05 = 0; // 开始I2C通信
|
||||
// 设置指定通道的PWM值
|
||||
#if PCA9685_USE_SOFT_IIC == 1
|
||||
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, (PCA9685_LED0_ON_L + 4 * channel) & 0xFF, on & 0xFF);
|
||||
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, (PCA9685_LED0_ON_H + 4 * channel) & 0xFF, (on >> 8) & 0xFF);
|
||||
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, (PCA9685_LED0_OFF_L + 4 * channel) & 0xFF, off & 0xFF);
|
||||
soft_iic_write_reg(&config, PCA9685_I2C_ADDR, (PCA9685_LED0_OFF_H + 4 * channel) & 0xFF, (off >> 8) & 0xFF);
|
||||
#else
|
||||
iic_write_reg(PCA9685_I2C_ADDR, (PCA9685_LED0_ON_L + 4 * channel) & 0xFF, on & 0xFF);
|
||||
iic_write_reg(PCA9685_I2C_ADDR, (PCA9685_LED0_ON_H + 4 * channel) & 0xFF, (on >> 8) & 0xFF);
|
||||
iic_write_reg(PCA9685_I2C_ADDR, (PCA9685_LED0_OFF_L + 4 * channel) & 0xFF, off & 0xFF);
|
||||
iic_write_reg(PCA9685_I2C_ADDR, (PCA9685_LED0_OFF_H + 4 * channel) & 0xFF, (off >> 8) & 0xFF);
|
||||
// P05 = 1; // 结束I2C通信
|
||||
#endif
|
||||
}
|
||||
69
Source/button.c
Normal file
69
Source/button.c
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "button.h"
|
||||
|
||||
uint32 button_press_time = 0; // 按钮按下时间计数
|
||||
static volatile button_status_enum button_status = BUTTON_NO_PRESS; // 按钮LED状态
|
||||
|
||||
void button_init()
|
||||
{
|
||||
gpio_mode(BUTTON_LED_R, GPO_PP);
|
||||
gpio_mode(BUTTON_LED_G, GPO_PP);
|
||||
gpio_mode(BUTTON_LED_O, GPO_PP);
|
||||
gpio_set_level(BUTTON_LED_R, 0);
|
||||
gpio_set_level(BUTTON_LED_G, 0);
|
||||
gpio_set_level(BUTTON_LED_O, 0);
|
||||
|
||||
gpio_pull_set(BUTTON_NO_PIN, PULLUP); // 设置按钮引脚
|
||||
gpio_pull_set(BUTTON_NC_PIN, PULLUP); // 设置按钮引脚
|
||||
gpio_mode(BUTTON_NO_PIN, GPIO); // 设置按钮引脚为输入模式
|
||||
gpio_mode(BUTTON_NC_PIN, GPIO); // 设置按钮引脚为输入模式
|
||||
// PINIPH |= 0x01;
|
||||
// PINIPL |= 0x01;
|
||||
// P0IM0 &= 0x3F;
|
||||
// P0IM1 &= 0x3F;
|
||||
// P0INTE |= 0xC0;
|
||||
}
|
||||
|
||||
void button_1ms_callback()
|
||||
{
|
||||
if(gpio_get_level(BUTTON_NO_PIN) == 0)
|
||||
{
|
||||
button_press_time ++;
|
||||
if(button_press_time >= 10000) // 防止溢出
|
||||
{
|
||||
button_press_time = 10000; // 限制最大值
|
||||
}
|
||||
}
|
||||
else if(gpio_get_level(BUTTON_NC_PIN) == 0)
|
||||
{
|
||||
button_press_time = 0;
|
||||
button_status = BUTTON_NO_PRESS; // 按钮未按下
|
||||
}
|
||||
if(button_press_time >= BUTTON_LONG_PRESS_TIME)
|
||||
{
|
||||
button_status = BUTTON_LONG_PRESS; // 设置按钮状态为长按
|
||||
}
|
||||
else if(button_press_time >= BUTTON_SHORT_PRESS_TIME && button_status != BUTTON_SHORT_PRESS_HANDLED)
|
||||
{
|
||||
button_status = BUTTON_SHORT_PRESS; // 设置按钮状态为短按
|
||||
}
|
||||
}
|
||||
|
||||
button_status_enum button_get_status()
|
||||
{
|
||||
if(button_status == BUTTON_SHORT_PRESS)
|
||||
{
|
||||
button_status = BUTTON_SHORT_PRESS_HANDLED; // 短按已处理
|
||||
return BUTTON_SHORT_PRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return button_status;
|
||||
}
|
||||
}
|
||||
|
||||
void button_led_set(button_led_enum led)
|
||||
{
|
||||
gpio_set_level(BUTTON_LED_R, led == BUTTON_LED_R);
|
||||
gpio_set_level(BUTTON_LED_G, led == BUTTON_LED_G);
|
||||
gpio_set_level(BUTTON_LED_O, led == BUTTON_LED_O);
|
||||
}
|
||||
200
Source/clock_init.c
Normal file
200
Source/clock_init.c
Normal file
@@ -0,0 +1,200 @@
|
||||
#include "clock_init.h"
|
||||
#include "delay.h"
|
||||
#include "uart.h"
|
||||
|
||||
//22.11MHz的IRC参数寄存器 0xFB
|
||||
//24MHz的IRC参数寄存器 0xFB
|
||||
#define IRC_22M (*((uint8 idata*)0xFA))
|
||||
#define IRC_24M (*((uint8 idata*)0xFB))
|
||||
|
||||
|
||||
//内核频率
|
||||
int32 sys_clk = FOSC;
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief STC32G设置系统频率
|
||||
// @param NULL 空值
|
||||
// @return void 系统频率
|
||||
// Sample usage:
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint32 set_clk(void)
|
||||
{
|
||||
|
||||
P_SW2 |= 0x80;
|
||||
|
||||
if(sys_clk == 22118400)
|
||||
{
|
||||
//选择 22.1184MHz
|
||||
CLKDIV = 0x04;
|
||||
IRTRIM = T22M_ADDR;
|
||||
VRTRIM = VRT27M_ADDR;
|
||||
IRCBAND = 0x02;
|
||||
CLKDIV = 0x00;
|
||||
}
|
||||
else if(sys_clk == 24000000)
|
||||
{
|
||||
//选择 24MHz
|
||||
CLKDIV = 0x04;
|
||||
IRTRIM = T24M_ADDR;
|
||||
VRTRIM = VRT27M_ADDR;
|
||||
IRCBAND = 0x02;
|
||||
CLKDIV = 0x00;
|
||||
}
|
||||
else if(sys_clk == 27000000)
|
||||
{
|
||||
//选择 27MHz
|
||||
CLKDIV = 0x04;
|
||||
IRTRIM = T27M_ADDR;
|
||||
VRTRIM = VRT27M_ADDR;
|
||||
IRCBAND = 0x02;
|
||||
CLKDIV = 0x00;
|
||||
}
|
||||
else if(sys_clk == 30000000)
|
||||
{
|
||||
|
||||
//选择 30MHz
|
||||
CLKDIV = 0x04;
|
||||
IRTRIM = T30M_ADDR;
|
||||
VRTRIM = VRT27M_ADDR;
|
||||
IRCBAND = 0x02;
|
||||
CLKDIV = 0x00;
|
||||
}
|
||||
else if(sys_clk == 33177600)
|
||||
{
|
||||
//选择 33.1776MHz
|
||||
CLKDIV = 0x04;
|
||||
IRTRIM = T33M_ADDR;
|
||||
VRTRIM = VRT27M_ADDR;
|
||||
IRCBAND = 0x02;
|
||||
CLKDIV = 0x00;
|
||||
}
|
||||
else if(sys_clk == 35000000)
|
||||
{
|
||||
//选择 35MHz
|
||||
CLKDIV = 0x04;
|
||||
IRTRIM = T35M_ADDR;
|
||||
VRTRIM = VRT44M_ADDR;
|
||||
IRCBAND = 0x03;
|
||||
CLKDIV = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_clk = 30000000;
|
||||
//选择 30MHz
|
||||
CLKDIV = 0x04;
|
||||
IRTRIM = T30M_ADDR;
|
||||
VRTRIM = VRT27M_ADDR;
|
||||
IRCBAND = 0x02;
|
||||
CLKDIV = 0x00;
|
||||
}
|
||||
|
||||
return sys_clk;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
EAXFR = 1; // 使能访问XFR
|
||||
CKCON = 0x00; // 设置外部数据总线为最快
|
||||
WTST = 0; // 设置程序代码等待参数,赋值为0可将CPU执行程序的速度设置为最快
|
||||
SET_P54_RESRT; // 使P54为复位引脚
|
||||
P_SW2 = 0x80; // 开启特殊地址访问
|
||||
|
||||
#if (1 == EXTERNAL_CRYSTA_ENABLE)
|
||||
XOSCCR = 0xc0; //启动外部晶振
|
||||
while (!(XOSCCR & 1)); //等待时钟稳定
|
||||
CLKDIV = 0x00; //时钟不分频
|
||||
CLKSEL = 0x01; //选择外部晶振
|
||||
#else
|
||||
//自动设置系统频率
|
||||
#if (0 == FOSC)
|
||||
sys_clk = set_clk();
|
||||
#else
|
||||
sys_clk = FOSC;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
delay_init(); //延时函数初始化
|
||||
|
||||
WTST = 0;
|
||||
P_SW2 |= 0x80;
|
||||
CLKDIV = 0; //24MHz主频,分频设置
|
||||
|
||||
P0M0 = 0x00;
|
||||
P0M1 = 0x00;
|
||||
P1M0 = 0x00;
|
||||
P1M1 = 0x00;
|
||||
P2M0 = 0x00;
|
||||
P2M1 = 0x00;
|
||||
P3M0 = 0x00;
|
||||
P3M1 = 0x00;
|
||||
P4M0 = 0x00;
|
||||
P4M1 = 0x00;
|
||||
P5M0 = 0x00;
|
||||
P5M1 = 0x00;
|
||||
P6M0 = 0x00;
|
||||
P6M1 = 0x00;
|
||||
P7M0 = 0x00;
|
||||
P7M1 = 0x00;
|
||||
|
||||
ADCCFG = 0;
|
||||
AUXR = 0;
|
||||
SCON = 0;
|
||||
S2CON = 0;
|
||||
S3CON = 0;
|
||||
S4CON = 0;
|
||||
P_SW1 = 0;
|
||||
IE2 = 0;
|
||||
TMOD = 0;
|
||||
|
||||
P_SW2 |= 0x80;
|
||||
|
||||
#if (1 == USE_USB_CDC)
|
||||
P3M0 &= ~0x03;
|
||||
P3M1 |= 0x03;
|
||||
|
||||
IRC48MCR = 0x80;
|
||||
while (!(IRC48MCR & 0x01));
|
||||
|
||||
USBCLK = 0x00;
|
||||
USBCON = 0x90;
|
||||
usb_init();
|
||||
IE2 |= 0x80;
|
||||
EA = 1;
|
||||
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
|
||||
#else
|
||||
uart_init(DEBUG_UART, DEBUG_UART_RX_PIN, DEBUG_UART_TX_PIN, DEBUG_UART_BAUD, DEBUG_UART_TIM);
|
||||
#endif
|
||||
EnableGlobalIRQ();
|
||||
}
|
||||
|
||||
|
||||
#if (1 == PRINTF_ENABLE)
|
||||
#if (1==USE_USB_CDC)
|
||||
#else
|
||||
//重定义printf 数字 只能输出uint16
|
||||
char putchar(char c)
|
||||
{
|
||||
uart_putchar(DEBUG_UART, c);//把自己实现的串口打印一字节数据的函数替换到这里
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void DisableGlobalIRQ(void)
|
||||
{
|
||||
EA = 0;
|
||||
}
|
||||
|
||||
|
||||
void EnableGlobalIRQ(void)
|
||||
{
|
||||
EA = 1;
|
||||
}
|
||||
|
||||
141
Source/command.c
Normal file
141
Source/command.c
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "command.h"
|
||||
|
||||
uint8 command_buffer[COMMAND_BUFFER_SIZE]; // 命令缓冲区
|
||||
static uint8 command_buffer_index = 0; // 当前命令索引
|
||||
static vuint8 is_busy_command = 0;
|
||||
|
||||
/************************************************************
|
||||
* 名称 :getIntFromStr()
|
||||
* 功能 :从字符串中获取整数
|
||||
* 输入 :void
|
||||
* 输出 :int
|
||||
* 说明 :从字符串中获取整数,自动移动指针,遇到特殊字符停止
|
||||
************************************************************/
|
||||
int16 getIntFromStr()
|
||||
{
|
||||
int16 result = 0;
|
||||
int8 is_negative = 1; // 是否为负数
|
||||
bit has_get = 0;
|
||||
while(command_buffer[command_buffer_index])
|
||||
{
|
||||
if(command_buffer[command_buffer_index] == ' ' || command_buffer[command_buffer_index] == ';' || command_buffer[command_buffer_index] == '\r' || command_buffer[command_buffer_index] == '\n' || command_buffer[command_buffer_index] == '\0')
|
||||
{
|
||||
if(has_get)
|
||||
{
|
||||
break;
|
||||
}
|
||||
command_buffer_index++;
|
||||
continue;
|
||||
}
|
||||
else if(command_buffer[command_buffer_index] == '-')
|
||||
{
|
||||
is_negative = -1;
|
||||
}
|
||||
else if(command_buffer[command_buffer_index] >= '0' && command_buffer[command_buffer_index] <= '9')
|
||||
{
|
||||
has_get = 1;
|
||||
result = result*10 + command_buffer[command_buffer_index] - '0';
|
||||
}
|
||||
else if(command_buffer[command_buffer_index] == '.')
|
||||
{
|
||||
command_buffer_index++;
|
||||
while(command_buffer[command_buffer_index] >= '0' && command_buffer[command_buffer_index] <= '9')command_buffer_index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
command_buffer_index++;
|
||||
}
|
||||
return result * is_negative; // 返回结果
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
* 名称 :startWith()
|
||||
* 功能 :判断字符串是否以某个字符串开头
|
||||
* 输入 :uint8 *str,uint8 *cmd,uint8 offset
|
||||
* 输出 uint8
|
||||
* 说明 :判断字符串是否以某个字符串开头
|
||||
************************************************************/
|
||||
uint8 startWith(uint8 *str, uint8 *cmd,uint8 offset,uint8 *counter)
|
||||
{
|
||||
uint8 cou,k;
|
||||
k = offset;
|
||||
for(cou=0;*cmd;cou++)
|
||||
{
|
||||
if(*(str+cou+k) != *cmd)
|
||||
{
|
||||
(*counter) -= cou;
|
||||
return 0;
|
||||
}
|
||||
cmd++;
|
||||
(*counter) ++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
* 名称 :parseCommand()
|
||||
* 功能 :解析命令
|
||||
* 输入 :无
|
||||
* 输出 :无
|
||||
* 说明 :解析命令
|
||||
************************************************************/
|
||||
void parseCommand()
|
||||
{
|
||||
uint8 cmd_state = 1; // 命令状态
|
||||
if(!is_busy_command) return; // 如果没有忙状态,直接返回
|
||||
command_buffer[command_buffer_index] = '\0';
|
||||
command_buffer_index = 0;
|
||||
if(startWith(command_buffer,"POW",0,&command_buffer_index))
|
||||
{
|
||||
// command_buffer_index += 2;
|
||||
if(command_buffer[command_buffer_index] == ' ')
|
||||
{
|
||||
// int16 power_index = 1000;
|
||||
// power_index = getIntFromStr();
|
||||
// if(startWith(command_buffer," ON",command_buffer_index,&command_buffer_index))
|
||||
// {
|
||||
|
||||
// }
|
||||
// else if(startWith(command_buffer," OFF",command_buffer_index,&command_buffer_index))
|
||||
// {
|
||||
|
||||
// }
|
||||
// if(command_buffer[command_buffer_index] == ';')
|
||||
// {
|
||||
// cmd_state = 0; // 命令成功
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(cmd_state)
|
||||
{
|
||||
printf("Error!\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("OK!\r\n");
|
||||
}
|
||||
command_buffer_index = 0;
|
||||
is_busy_command = 0;
|
||||
}
|
||||
|
||||
|
||||
void command_uart_callback(uint8 dat)
|
||||
{
|
||||
if(is_busy_command) return;
|
||||
command_buffer[command_buffer_index++] = dat;
|
||||
if(command_buffer[command_buffer_index-1] == ';')
|
||||
{
|
||||
is_busy_command = 1; // 设置忙状态,防止中断嵌套
|
||||
}
|
||||
if(command_buffer_index >= COMMAND_BUFFER_SIZE)
|
||||
{
|
||||
command_buffer_index = 0; // 防止缓冲区溢出
|
||||
}
|
||||
}
|
||||
51
Source/delay.c
Normal file
51
Source/delay.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "delay.h"
|
||||
|
||||
|
||||
static vuint16 delay_ms_a = 0;
|
||||
static vuint16 delay_us_a = 0;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 软件延时函数初始化
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void delay_init(void)
|
||||
{
|
||||
delay_ms_a = sys_clk / 6000;
|
||||
delay_us_a = sys_clk / 7000000;
|
||||
if(sys_clk <= 12000000) delay_us_a++;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 软件延时函数
|
||||
// @param x 需要延时的时间(ms)
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void delay_ms(uint16 ms)
|
||||
{
|
||||
uint16 i;
|
||||
do {
|
||||
i = delay_ms_a;
|
||||
//i = sys_clk/6000;//参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
|
||||
while(--i);
|
||||
}while(--ms);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 软件延时函数(这是一个不准确的延时)
|
||||
// @param x 需要延时的时间(us)
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void delay_us(uint32 us)
|
||||
{
|
||||
uint16 i;
|
||||
do {
|
||||
i = delay_us_a;
|
||||
//i = sys_clk/6000;//参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
|
||||
while(--i);
|
||||
}while(--us);
|
||||
}
|
||||
38
Source/exti.c
Normal file
38
Source/exti.c
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "exti.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 外部中断初始化
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: exit_init(INT0_P32,BOTH) //初始化P32 作为外部中断引脚,双边沿触发。
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void exit_init(INTN_enum int_n,INT_MODE_enum mode)
|
||||
{
|
||||
if(INT0_P32 == int_n)
|
||||
{
|
||||
IT0 = mode;
|
||||
EX0 = 1; //使能INT0中断
|
||||
}
|
||||
|
||||
if(INT1_P33 == int_n)
|
||||
{
|
||||
IT1 = mode;
|
||||
EX1 = 1; //使能INT1中断
|
||||
}
|
||||
|
||||
if(INT2_P36 == int_n)
|
||||
{
|
||||
INTCLKO |= 1<<4; //使能INT2中断
|
||||
}
|
||||
|
||||
if(INT3_P37 == int_n)
|
||||
{
|
||||
INTCLKO |= 1<<5; //使能INT3中断
|
||||
}
|
||||
|
||||
if(INT4_P30 == int_n)
|
||||
{
|
||||
INTCLKO |= 1<<6; //使能INT4中断
|
||||
}
|
||||
|
||||
}
|
||||
523
Source/fifo.c
Normal file
523
Source/fifo.c
Normal file
@@ -0,0 +1,523 @@
|
||||
#include "fifo.h"
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// 函数简介 FIFO 头指针位移
|
||||
// 参数说明 *fifo FIFO 对象指针
|
||||
// 参数说明 offset 偏移量
|
||||
// 返回参数 void
|
||||
// 使用示例 fifo_head_offset(fifo, 1);
|
||||
// 备注信息 本函数在文件内部调用 用户不用关注 也不可修改
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
static void fifo_head_offset (fifo_struct *fifo, uint32 offset)
|
||||
{
|
||||
fifo->head += offset;
|
||||
|
||||
while(fifo->max <= fifo->head) // 如果范围超过则减缓冲区大小 直到小于最大缓冲区大小
|
||||
{
|
||||
fifo->head -= fifo->max;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// 函数简介 FIFO 尾指针位移
|
||||
// 参数说明 *fifo FIFO 对象指针
|
||||
// 参数说明 offset 偏移量
|
||||
// 返回参数 void
|
||||
// 使用示例 fifo_end_offset(fifo, 1);
|
||||
// 备注信息 本函数在文件内部调用 用户不用关注 也不可修改
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
static void fifo_end_offset (fifo_struct *fifo, uint32 offset)
|
||||
{
|
||||
fifo->end += offset;
|
||||
|
||||
while(fifo->max <= fifo->end) // 如果范围超过则减缓冲区大小 直到小于最大缓冲区大小
|
||||
{
|
||||
fifo->end -= fifo->max;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// 函数简介 FIFO 重置缓冲器
|
||||
// 参数说明 *fifo FIFO 对象指针
|
||||
// 返回参数 void
|
||||
// 使用示例 fifo_clear(fifo);
|
||||
// 备注信息 清空当前 FIFO 对象的内存
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
fifo_state_enum fifo_clear (fifo_struct *fifo)
|
||||
{
|
||||
//zf_assert(NULL != fifo);
|
||||
fifo_state_enum return_state = FIFO_SUCCESS; // 操作结果初值
|
||||
do
|
||||
{
|
||||
// if(FIFO_IDLE != fifo->execution) // 判断是否当前 FIFO 是否空闲
|
||||
// {
|
||||
// return_state = FIFO_RESET_UNDO; // 重置操作未完成
|
||||
// break;
|
||||
// }
|
||||
fifo->execution |= FIFO_RESET; // 重置操作置位
|
||||
fifo->head = 0; // 重置 FIFO 所有数值复位
|
||||
fifo->end = 0; // 重置 FIFO 所有数值复位
|
||||
fifo->reamin_size = fifo->max; // 重置 FIFO 所有数值复位
|
||||
switch(fifo->type)
|
||||
{
|
||||
case FIFO_DATA_8BIT: memset(fifo->buffer, 0, (uint16)fifo->max); break;
|
||||
case FIFO_DATA_16BIT: memset(fifo->buffer, 0, (uint16)fifo->max * 2); break;
|
||||
case FIFO_DATA_32BIT: memset(fifo->buffer, 0, (uint16)fifo->max * 4); break;
|
||||
}
|
||||
fifo->execution = FIFO_IDLE; // 操作状态复位
|
||||
}while(0);
|
||||
return return_state;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// 函数简介 FIFO 查询当前数据个数
|
||||
// 参数说明 *fifo FIFO 对象指针
|
||||
// 返回参数 uint32 已使用长度
|
||||
// 使用示例 uint32 len = fifo_used(fifo);
|
||||
// 备注信息
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint32 fifo_used (fifo_struct *fifo)
|
||||
{
|
||||
//zf_assert(fifo != NULL);
|
||||
return (fifo->max - fifo->reamin_size); // 返回当前 FIFO 缓冲区中数据个数
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// 函数简介 向 FIFO 中写入数据
|
||||
// 参数说明 *fifo FIFO 对象指针
|
||||
// 参数说明 dat 数据
|
||||
// 返回参数 fifo_state_enum 操作状态
|
||||
// 使用示例 zf_log(fifo_write_element(&fifo, data) == FIFO_SUCCESS, "fifo_write_byte error");
|
||||
// 备注信息
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
fifo_state_enum fifo_write_element (fifo_struct *fifo, uint32 dat)
|
||||
{
|
||||
//zf_assert(NULL != fifo);
|
||||
fifo_state_enum return_state = FIFO_SUCCESS; // 操作结果初值
|
||||
|
||||
do
|
||||
{
|
||||
if((FIFO_RESET | FIFO_WRITE) & fifo->execution) // 不在写入与重置状态 避免写入竞争与指向错误
|
||||
{
|
||||
return_state = FIFO_WRITE_UNDO; // 写入操作未完成
|
||||
break;
|
||||
}
|
||||
fifo->execution |= FIFO_WRITE; // 写入操作置位
|
||||
|
||||
if(1 <= fifo->reamin_size) // 剩余空间足够装下本次数据
|
||||
{
|
||||
switch(fifo->type)
|
||||
{
|
||||
case FIFO_DATA_8BIT: ((uint8 *)fifo->buffer)[fifo->head] = dat; break;
|
||||
case FIFO_DATA_16BIT: ((uint16 *)fifo->buffer)[fifo->head] = dat; break;
|
||||
case FIFO_DATA_32BIT: ((uint32 *)fifo->buffer)[fifo->head] = dat; break;
|
||||
}
|
||||
fifo_head_offset(fifo, 1); // 头指针偏移
|
||||
fifo->reamin_size -= 1; // 缓冲区剩余长度减小
|
||||
}
|
||||
else
|
||||
{
|
||||
return_state = FIFO_SPACE_NO_ENOUGH; // 当前 FIFO 缓冲区满 不能再写入数据 返回空间不足
|
||||
}
|
||||
fifo->execution &= ~FIFO_WRITE; // 写入操作复位
|
||||
}while(0);
|
||||
|
||||
return return_state;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// 函数简介 向 FIFO 中写入数据
|
||||
// 参数说明 *fifo FIFO 对象指针
|
||||
// 参数说明 *dat 数据来源缓冲区指针
|
||||
// 参数说明 length 需要写入的数据长度
|
||||
// 返回参数 fifo_state_enum 操作状态
|
||||
// 使用示例 zf_log(fifo_write_buffer(&fifo, data, 32) == FIFO_SUCCESS, "fifo_write_buffer error");
|
||||
// 备注信息
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
fifo_state_enum fifo_write_buffer (fifo_struct *fifo, void *dat, uint32 length)
|
||||
{
|
||||
//zf_assert(NULL != fifo);
|
||||
fifo_state_enum return_state = FIFO_SUCCESS; // 操作结果初值
|
||||
uint32 temp_length = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if(NULL == dat)
|
||||
{
|
||||
return_state = FIFO_BUFFER_NULL; // 用户缓冲区异常
|
||||
break;
|
||||
}
|
||||
if((FIFO_RESET | FIFO_WRITE) & fifo->execution) // 不在写入与重置状态 避免写入竞争与指向错误
|
||||
{
|
||||
return_state = FIFO_WRITE_UNDO; // 写入操作未完成
|
||||
break;
|
||||
}
|
||||
fifo->execution |= FIFO_WRITE; // 写入操作置位
|
||||
|
||||
if(length <= fifo->reamin_size) // 剩余空间足够装下本次数据
|
||||
{
|
||||
temp_length = fifo->max - fifo->head; // 计算头指针距离缓冲区尾还有多少空间
|
||||
|
||||
if(length > temp_length) // 距离缓冲区尾长度不足写入数据 环形缓冲区分段操作
|
||||
{
|
||||
switch(fifo->type)
|
||||
{
|
||||
case FIFO_DATA_8BIT:
|
||||
{
|
||||
memcpy(
|
||||
&(((uint8 *)fifo->buffer)[fifo->head]),
|
||||
dat, (uint16)temp_length); // 拷贝第一段数据
|
||||
fifo_head_offset(fifo, temp_length); // 头指针偏移
|
||||
memcpy(
|
||||
&(((uint8 *)fifo->buffer)[fifo->head]),
|
||||
&(((uint8 *)dat)[temp_length]),
|
||||
(uint16)(length - temp_length)); // 拷贝第二段数据
|
||||
fifo_head_offset(fifo, length - temp_length); // 头指针偏移
|
||||
}break;
|
||||
case FIFO_DATA_16BIT:
|
||||
{
|
||||
memcpy(
|
||||
&(((uint16 *)fifo->buffer)[fifo->head]),
|
||||
dat, temp_length * 2); // 拷贝第一段数据
|
||||
fifo_head_offset(fifo, temp_length); // 头指针偏移
|
||||
memcpy(
|
||||
&(((uint16 *)fifo->buffer)[fifo->head]),
|
||||
&(((uint16 *)dat)[temp_length]),
|
||||
(length - temp_length) * 2); // 拷贝第二段数据
|
||||
fifo_head_offset(fifo, length - temp_length); // 头指针偏移
|
||||
}break;
|
||||
case FIFO_DATA_32BIT:
|
||||
{
|
||||
memcpy(
|
||||
&(((uint32 *)fifo->buffer)[fifo->head]),
|
||||
dat, temp_length * 4); // 拷贝第一段数据
|
||||
fifo_head_offset(fifo, temp_length); // 头指针偏移
|
||||
memcpy(
|
||||
&(((uint32 *)fifo->buffer)[fifo->head]),
|
||||
&(((uint32 *)dat)[temp_length]),
|
||||
(length - temp_length) * 4); // 拷贝第二段数据
|
||||
fifo_head_offset(fifo, length - temp_length); // 头指针偏移
|
||||
}break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(fifo->type)
|
||||
{
|
||||
case FIFO_DATA_8BIT:
|
||||
{
|
||||
memcpy(
|
||||
&(((uint8 *)fifo->buffer)[fifo->head]),
|
||||
dat, (uint16)length); // 一次完整写入
|
||||
fifo_head_offset(fifo, length); // 头指针偏移
|
||||
}break;
|
||||
case FIFO_DATA_16BIT:
|
||||
{
|
||||
memcpy(
|
||||
&(((uint16 *)fifo->buffer)[fifo->head]),
|
||||
dat, length * 2); // 一次完整写入
|
||||
fifo_head_offset(fifo, length); // 头指针偏移
|
||||
}break;
|
||||
case FIFO_DATA_32BIT:
|
||||
{
|
||||
memcpy(
|
||||
&(((uint32 *)fifo->buffer)[fifo->head]),
|
||||
dat, length * 4); // 一次完整写入
|
||||
fifo_head_offset(fifo, length); // 头指针偏移
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
fifo->reamin_size -= length; // 缓冲区剩余长度减小
|
||||
}
|
||||
else
|
||||
{
|
||||
return_state = FIFO_SPACE_NO_ENOUGH; // 当前 FIFO 缓冲区满 不能再写入数据 返回空间不足
|
||||
}
|
||||
fifo->execution &= ~FIFO_WRITE; // 写入操作复位
|
||||
}while(0);
|
||||
|
||||
return return_state;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// 函数简介 从 FIFO 读取数据
|
||||
// 参数说明 *fifo FIFO 对象指针
|
||||
// 参数说明 *dat 目标缓冲区指针
|
||||
// 参数说明 flag 是否变更 FIFO 状态 可选择是否清空读取的数据
|
||||
// 返回参数 fifo_state_enum 操作状态
|
||||
// 使用示例 zf_log(fifo_read_element(&fifo, data, FIFO_READ_ONLY) == FIFO_SUCCESS, "fifo_read_byte error");
|
||||
// 备注信息
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
fifo_state_enum fifo_read_element (fifo_struct *fifo, void *dat, fifo_operation_enum flag)
|
||||
{
|
||||
//zf_assert(NULL != fifo);
|
||||
fifo_state_enum return_state = FIFO_SUCCESS; // 操作结果初值
|
||||
|
||||
do
|
||||
{
|
||||
if(NULL == dat)
|
||||
{
|
||||
return_state = FIFO_BUFFER_NULL; // 用户缓冲区异常
|
||||
}
|
||||
else
|
||||
{
|
||||
if((FIFO_RESET | FIFO_CLEAR) & fifo->execution) // 判断是否当前 FIFO 是否在执行清空或重置操作
|
||||
{
|
||||
return_state = FIFO_READ_UNDO; // 读取操作未完成
|
||||
break;
|
||||
}
|
||||
|
||||
if(1 > fifo_used(fifo))
|
||||
{
|
||||
return_state = FIFO_DATA_NO_ENOUGH; // 缓冲区没有数据 返回数据长度不足
|
||||
break; // 直接退出操作
|
||||
}
|
||||
|
||||
fifo->execution |= FIFO_READ; // 读操作置位
|
||||
switch(fifo->type)
|
||||
{
|
||||
case FIFO_DATA_8BIT: *((uint8 *)dat) = ((uint8 *)fifo->buffer)[fifo->end]; break;
|
||||
case FIFO_DATA_16BIT: *((uint16 *)dat) = ((uint16 *)fifo->buffer)[fifo->end]; break;
|
||||
case FIFO_DATA_32BIT: *((uint32 *)dat) = ((uint32 *)fifo->buffer)[fifo->end]; break;
|
||||
}
|
||||
fifo->execution &= ~FIFO_READ; // 读操作复位
|
||||
}
|
||||
|
||||
if(FIFO_READ_AND_CLEAN == flag) // 如果选择读取并更改 FIFO 状态
|
||||
{
|
||||
if((FIFO_RESET | FIFO_CLEAR | FIFO_READ) == fifo->execution) // 不在 重置 清空 读取 状态 避免异常
|
||||
{
|
||||
return_state = FIFO_CLEAR_UNDO; // 清空操作未完成
|
||||
break;
|
||||
}
|
||||
fifo->execution |= FIFO_CLEAR; // 清空作置位
|
||||
fifo_end_offset(fifo, 1); // 移动 FIFO 头指针
|
||||
fifo->reamin_size += 1; // 释放对应长度空间
|
||||
fifo->execution &= ~FIFO_CLEAR; // 清空作复位
|
||||
}
|
||||
}while(0);
|
||||
|
||||
return return_state;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// 函数简介 从 FIFO 读取数据
|
||||
// 参数说明 *fifo FIFO 对象指针
|
||||
// 参数说明 *dat 目标缓冲区指针
|
||||
// 参数说明 *length 读取的数据长度 如果没有这么多数据这里会被修改
|
||||
// 参数说明 flag 是否变更 FIFO 状态 可选择是否清空读取的数据
|
||||
// 返回参数 fifo_state_enum 操作状态
|
||||
// 使用示例 zf_log(fifo_read_buffer(&fifo, data, &length, FIFO_READ_ONLY) == FIFO_SUCCESS, "fifo_read_buffer error");
|
||||
// 备注信息
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
fifo_state_enum fifo_read_buffer (fifo_struct *fifo, void *dat, uint32 *length, fifo_operation_enum flag)
|
||||
{
|
||||
//zf_assert(NULL != fifo);
|
||||
//zf_assert(NULL != length);
|
||||
fifo_state_enum return_state = FIFO_SUCCESS; // 操作结果初值
|
||||
uint32 temp_length = 0;
|
||||
uint32 fifo_data_length = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if(NULL == dat)
|
||||
{
|
||||
return_state = FIFO_BUFFER_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((FIFO_RESET | FIFO_CLEAR) & fifo->execution) // 判断是否当前 FIFO 是否在执行清空或重置操作
|
||||
{
|
||||
*length = fifo_data_length; // 纠正读取的长度
|
||||
return_state = FIFO_READ_UNDO; // 读取操作未完成
|
||||
break;
|
||||
}
|
||||
|
||||
fifo_data_length = fifo_used(fifo); // 获取当前数据有多少
|
||||
if(*length > fifo_data_length) // 判断长度是否足够
|
||||
{
|
||||
*length = fifo_data_length; // 纠正读取的长度
|
||||
return_state = FIFO_DATA_NO_ENOUGH; // 标志数据不够
|
||||
if(0 == fifo_data_length) // 如果没有数据 就直接退出
|
||||
{
|
||||
fifo->execution &= ~FIFO_READ; // 读操作复位
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fifo->execution |= FIFO_READ; // 读操作置位
|
||||
temp_length = fifo->max - fifo->end; // 计算尾指针距离缓冲区尾还有多少空间
|
||||
if(*length <= temp_length) // 足够一次性读取完毕
|
||||
{
|
||||
switch(fifo->type)
|
||||
{
|
||||
case FIFO_DATA_8BIT: memcpy(dat, &(((uint8 *)fifo->buffer)[fifo->end]), (uint16)*length); break;
|
||||
case FIFO_DATA_16BIT: memcpy(dat, &(((uint16 *)fifo->buffer)[fifo->end]), (uint16)*length * 2); break;
|
||||
case FIFO_DATA_32BIT: memcpy(dat, &(((uint32 *)fifo->buffer)[fifo->end]), (uint16)*length * 4); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(fifo->type)
|
||||
{
|
||||
case FIFO_DATA_8BIT:
|
||||
{
|
||||
memcpy(dat, &(((uint8 *)fifo->buffer)[fifo->end]), (uint16)temp_length);
|
||||
memcpy(&(((uint8 *)dat)[temp_length]), fifo->buffer, (uint16)(*length - temp_length));
|
||||
}break;
|
||||
case FIFO_DATA_16BIT:
|
||||
{
|
||||
memcpy(dat, &(((uint16 *)fifo->buffer)[fifo->end]), (uint16)(temp_length * 2));
|
||||
memcpy(&(((uint16 *)dat)[temp_length]), fifo->buffer, (uint16)((*length - temp_length) * 2));
|
||||
}break;
|
||||
case FIFO_DATA_32BIT:
|
||||
{
|
||||
memcpy(dat, &(((uint32 *)fifo->buffer)[fifo->end]), (uint16)(temp_length * 4));
|
||||
memcpy(&(((uint32 *)dat)[temp_length]), fifo->buffer, (uint16)((*length - temp_length) * 4));
|
||||
}break;
|
||||
}
|
||||
}
|
||||
fifo->execution &= ~FIFO_READ; // 读操作复位
|
||||
}
|
||||
|
||||
if(FIFO_READ_AND_CLEAN == flag) // 如果选择读取并更改 FIFO 状态
|
||||
{
|
||||
if((FIFO_RESET | FIFO_CLEAR | FIFO_READ) == fifo->execution) // 不在 重置 清空 读取 状态 避免异常
|
||||
{
|
||||
return_state = FIFO_CLEAR_UNDO; // 清空操作未完成
|
||||
break;
|
||||
}
|
||||
fifo->execution |= FIFO_CLEAR; // 清空作置位
|
||||
fifo_end_offset(fifo, *length); // 移动 FIFO 头指针
|
||||
fifo->reamin_size += *length; // 释放对应长度空间
|
||||
fifo->execution &= ~FIFO_CLEAR; // 清空作复位
|
||||
}
|
||||
}while(0);
|
||||
|
||||
return return_state;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// 函数简介 从 FIFO 尾部读取指定长度 buffer
|
||||
// 参数说明 *fifo FIFO 对象指针
|
||||
// 参数说明 *dat 目标缓冲区指针
|
||||
// 参数说明 *length 读取的数据长度 如果没有这么多数据这里会被修改
|
||||
// 参数说明 flag 是否变更 FIFO 状态 可选择是否清空读取的数据
|
||||
// 返回参数 fifo_state_enum 操作状态
|
||||
// 使用示例 zf_log(fifo_read_tail_buffer(&fifo, data, &length, FIFO_READ_ONLY) == FIFO_SUCCESS, "fifo_read_buffer error");
|
||||
// 备注信息 如果使用 FIFO_READ_AND_CLEAN 操作 将会丢弃所有数据并清空整个 FIFO
|
||||
// 如果使用 FIFO_READ_AND_CLEAN 操作 将会丢弃所有数据并清空整个 FIFO
|
||||
// 如果使用 FIFO_READ_AND_CLEAN 操作 将会丢弃所有数据并清空整个 FIFO
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
fifo_state_enum fifo_read_tail_buffer (fifo_struct *fifo, void *dat, uint32 *length, fifo_operation_enum flag)
|
||||
{
|
||||
//zf_assert(NULL != fifo);
|
||||
//zf_assert(NULL != length);
|
||||
fifo_state_enum return_state = FIFO_SUCCESS; // 操作结果初值
|
||||
uint32 temp_length = 0;
|
||||
uint32 fifo_data_length = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if(NULL == dat)
|
||||
{
|
||||
return_state = FIFO_BUFFER_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((FIFO_RESET | FIFO_CLEAR | FIFO_WRITE) & fifo->execution) // 判断是否当前 FIFO 是否在执行清空或重置操作
|
||||
{
|
||||
*length = fifo_data_length; // 纠正读取的长度
|
||||
return_state = FIFO_READ_UNDO; // 读取操作未完成
|
||||
break;
|
||||
}
|
||||
|
||||
fifo_data_length = fifo_used(fifo); // 获取当前数据有多少
|
||||
if(*length > fifo_data_length) // 判断长度是否足够
|
||||
{
|
||||
*length = fifo_data_length; // 纠正读取的长度
|
||||
return_state = FIFO_DATA_NO_ENOUGH; // 标志数据不够
|
||||
if(0 == fifo_data_length) // 如果没有数据 就直接退出
|
||||
{
|
||||
fifo->execution &= ~FIFO_READ; // 读操作复位
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fifo->execution |= FIFO_READ; // 读操作置位
|
||||
if((fifo->head > fifo->end) || (fifo->head >= *length))
|
||||
{
|
||||
switch(fifo->type)
|
||||
{
|
||||
case FIFO_DATA_8BIT: memcpy(dat, &(((uint8 *)fifo->buffer)[fifo->head - *length]), (uint16)*length); break;
|
||||
case FIFO_DATA_16BIT: memcpy(dat, &(((uint16 *)fifo->buffer)[fifo->head - *length]), (uint16)(*length * 2));break;
|
||||
case FIFO_DATA_32BIT: memcpy(dat, &(((uint32 *)fifo->buffer)[fifo->head - *length]), (uint16)(*length * 4));break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_length = *length - fifo->head; // 计算尾指针距离缓冲区尾还有多少空间
|
||||
switch(fifo->type)
|
||||
{
|
||||
case FIFO_DATA_8BIT:
|
||||
{
|
||||
memcpy(dat, &(((uint8 *)fifo->buffer)[fifo->max - temp_length]), (uint16)temp_length);
|
||||
memcpy(&(((uint8 *)dat)[temp_length]), &(((uint8 *)fifo->buffer)[fifo->head - *length]), (uint16)(*length - temp_length));
|
||||
}break;
|
||||
case FIFO_DATA_16BIT:
|
||||
{
|
||||
memcpy(dat, &(((uint16 *)fifo->buffer)[fifo->max - temp_length]), temp_length * 2);
|
||||
memcpy(&(((uint16 *)dat)[temp_length]), &(((uint16 *)fifo->buffer)[fifo->head - *length]), (uint16)((*length - temp_length) * 2));
|
||||
}break;
|
||||
case FIFO_DATA_32BIT:
|
||||
{
|
||||
memcpy(dat, &(((uint32 *)fifo->buffer)[fifo->max - temp_length]), temp_length * 4);
|
||||
memcpy(&(((uint32 *)dat)[temp_length]), &(((uint32 *)fifo->buffer)[fifo->head - *length]), (uint16)((*length - temp_length) * 4));
|
||||
}break;
|
||||
}
|
||||
}
|
||||
fifo->execution &= ~FIFO_READ; // 读操作复位
|
||||
}
|
||||
|
||||
if(FIFO_READ_AND_CLEAN == flag) // 如果选择读取并更改 FIFO 状态
|
||||
{
|
||||
if((FIFO_RESET | FIFO_CLEAR | FIFO_READ) == fifo->execution) // 不在 重置 清空 读取 状态 避免异常
|
||||
{
|
||||
return_state = FIFO_CLEAR_UNDO; // 清空操作未完成
|
||||
break;
|
||||
}
|
||||
fifo_clear(fifo);
|
||||
}
|
||||
}while(0);
|
||||
|
||||
return return_state;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// 函数简介 FIFO 初始化 挂载对应缓冲区
|
||||
// 参数说明 *fifo FIFO 对象指针
|
||||
// 参数说明 type FIFO 数据位数
|
||||
// 参数说明 *buffer_addr 要挂载的缓冲区
|
||||
// 参数说明 size 缓冲区大小
|
||||
// 返回参数 fifo_state_enum 操作状态
|
||||
// 使用示例 fifo_init(&user_fifo, user_buffer, 64);
|
||||
// 备注信息
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
fifo_state_enum fifo_init (fifo_struct *fifo, fifo_data_type_enum type, void *buffer_addr, uint32 len)
|
||||
{
|
||||
//zf_assert(NULL != fifo);
|
||||
fifo_state_enum return_state = FIFO_SUCCESS;
|
||||
do
|
||||
{
|
||||
fifo->buffer = buffer_addr;
|
||||
fifo->execution = FIFO_IDLE;
|
||||
fifo->type = type;
|
||||
fifo->head = 0;
|
||||
fifo->end = 0;
|
||||
fifo->reamin_size = len;
|
||||
fifo->max = len;
|
||||
}while(0);
|
||||
return return_state;
|
||||
}
|
||||
313
Source/gpio.c
Normal file
313
Source/gpio.c
Normal file
@@ -0,0 +1,313 @@
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
#define PxPU_BASE_ADDR 0x7EFE10
|
||||
|
||||
|
||||
void gpio_set_level(PIN_enum pin, uint8 level)
|
||||
{
|
||||
if(0x00 == (pin&0xF0)) //P0
|
||||
{
|
||||
if(level)
|
||||
P0 |= (1<<(pin&0xF));
|
||||
else
|
||||
P0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
else if(0x10 == (pin&0xF0)) //P1
|
||||
{
|
||||
if(level)
|
||||
P1 |= (1<<(pin&0xF));
|
||||
else
|
||||
P1 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
else if(0x20 == (pin&0xF0)) //P2
|
||||
{
|
||||
if(level)
|
||||
P2 |= (1<<(pin&0xF));
|
||||
else
|
||||
P2 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
else if(0x30 == (pin&0xF0)) //P3
|
||||
{
|
||||
if(level)
|
||||
P3 |= (1<<(pin&0xF));
|
||||
else
|
||||
P3 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
else if(0x40 == (pin&0xF0)) //P4
|
||||
{
|
||||
if(level)
|
||||
P4 |= (1<<(pin&0xF));
|
||||
else
|
||||
P4 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
else if(0x50 == (pin&0xF0)) //P5
|
||||
{
|
||||
if(level)
|
||||
P5 |= (1<<(pin&0xF));
|
||||
else
|
||||
P5 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
else if(0x60 == (pin&0xF0)) //P6
|
||||
{
|
||||
if(level)
|
||||
P6 |= (1<<(pin&0xF));
|
||||
else
|
||||
P6 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
else if(0x70 == (pin&0xF0)) //P7
|
||||
{
|
||||
if(level)
|
||||
P7 |= (1<<(pin&0xF));
|
||||
else
|
||||
P7 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
}
|
||||
|
||||
uint8 gpio_get_level(PIN_enum pin)
|
||||
{
|
||||
uint8 level;
|
||||
if(0x00 == (pin&0xF0)) //P0
|
||||
{
|
||||
level = (P0 & (1<<(pin&0xF))) ? 1 : 0;
|
||||
}
|
||||
else if(0x10 == (pin&0xF0)) //P1
|
||||
{
|
||||
level = (P1 & (1<<(pin&0xF))) ? 1 : 0;
|
||||
}
|
||||
else if(0x20 == (pin&0xF0)) //P2
|
||||
{
|
||||
level = (P2 & (1<<(pin&0xF))) ? 1 : 0;
|
||||
}
|
||||
else if(0x30 == (pin&0xF0)) //P3
|
||||
{
|
||||
level = (P3 & (1<<(pin&0xF))) ? 1 : 0;
|
||||
}
|
||||
else if(0x40 == (pin&0xF0)) //P4
|
||||
{
|
||||
level = (P4 & (1<<(pin&0xF))) ? 1 : 0;
|
||||
}
|
||||
else if(0x50 == (pin&0xF0)) //P5
|
||||
{
|
||||
level = (P5 & (1<<(pin&0xF))) ? 1 : 0;
|
||||
}
|
||||
else if(0x60 == (pin&0xF0)) //P6
|
||||
{
|
||||
level = (P6 & (1<<(pin&0xF))) ? 1 : 0;
|
||||
}
|
||||
else if(0x70 == (pin&0xF0)) //P7
|
||||
{
|
||||
level = (P7 & (1<<(pin&0xF))) ? 1 : 0;
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief GPIO设置引脚上拉电阻设置
|
||||
// @param pin 选择引脚(P0_0-P7_7)
|
||||
// @param pull 设置上下拉电阻 NOPULL:不设置 PULLUP:上拉
|
||||
// @return void
|
||||
// Sample usage: gpio_pull_set(P0_0,NOPULL); // 设置P0.0引脚没有上下拉电阻
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void gpio_pull_set(PIN_enum pin, PULL_enum pull)
|
||||
{
|
||||
if(PULLUP == pull)
|
||||
{
|
||||
(*(unsigned char volatile far *)(PxPU_BASE_ADDR + (pin >> 4))) |= (1<<(pin&0x0F));
|
||||
}
|
||||
else if(NOPULL == pull)
|
||||
{
|
||||
(*(unsigned char volatile far *)(PxPU_BASE_ADDR + (pin >> 4))) &= ~(1<<(pin&0x0F));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief GPIO设置引脚模式
|
||||
// @param pin 选择引脚(P0_0-P5_4)
|
||||
// @param mode 引脚模式 GPIO:准双向口, GPO_PP:推挽输出, GPI_IMPEDANCE:高阻输入, GPI_OD:开漏输出
|
||||
// @return void
|
||||
// Sample usage: gpio_mode(P0_0,GPIO); // 设置P0.0设置为双向IO
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void gpio_mode(PIN_enum pin, GPIOMODE_enum mode)
|
||||
{
|
||||
if(GPIO == mode)
|
||||
{
|
||||
if(0x00 == (pin&0xF0)) //P0
|
||||
{
|
||||
P0M1 &= ~(1<<(pin&0xF));
|
||||
P0M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x10 == (pin&0xF0)) //P1
|
||||
{
|
||||
P1M1 &= ~(1<<(pin&0xF));
|
||||
P1M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x20 == (pin&0xF0)) //P2
|
||||
{
|
||||
P2M1 &= ~(1<<(pin&0xF));
|
||||
P2M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
|
||||
if(0x30 == (pin&0xF0)) //P3
|
||||
{
|
||||
P3M1 &= ~(1<<(pin&0xF));
|
||||
P3M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x40 == (pin&0xF0)) //P4
|
||||
{
|
||||
P4M1 &= ~(1<<(pin&0xF));
|
||||
P4M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x50 == (pin&0xF0)) //P5
|
||||
{
|
||||
P5M1 &= ~(1<<(pin&0xF));
|
||||
P5M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x60 == (pin&0xF0)) //P5
|
||||
{
|
||||
P6M1 &= ~(1<<(pin&0xF));
|
||||
P6M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x70 == (pin&0xF0)) //P5
|
||||
{
|
||||
P7M1 &= ~(1<<(pin&0xF));
|
||||
P7M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
}
|
||||
else if(GPO_PP == mode)
|
||||
{
|
||||
if(0x00 == (pin&0xF0)) //P0
|
||||
{
|
||||
P0M1 &= ~(1<<(pin&0xF));
|
||||
P0M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x10 == (pin&0xF0)) //P1
|
||||
{
|
||||
P1M1 &= ~(1<<(pin&0xF));
|
||||
P1M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x20 == (pin&0xF0)) //P2
|
||||
{
|
||||
P2M1 &= ~(1<<(pin&0xF));
|
||||
P2M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
|
||||
if(0x30 == (pin&0xF0)) //P3
|
||||
{
|
||||
P3M1 &= ~(1<<(pin&0xF));
|
||||
P3M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x40 == (pin&0xF0)) //P4
|
||||
{
|
||||
P4M1 &= ~(1<<(pin&0xF));
|
||||
P4M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x50 == (pin&0xF0)) //P5
|
||||
{
|
||||
P5M1 &= ~(1<<(pin&0xF));
|
||||
P5M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x60 == (pin&0xF0)) //P4
|
||||
{
|
||||
P6M1 &= ~(1<<(pin&0xF));
|
||||
P6M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x70 == (pin&0xF0)) //P5
|
||||
{
|
||||
P7M1 &= ~(1<<(pin&0xF));
|
||||
P7M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
|
||||
}
|
||||
else if(GPI_IMPEDANCE == mode)
|
||||
{
|
||||
if(0x00 == (pin&0xF0)) //P0
|
||||
{
|
||||
P0M1 |= (1<<(pin&0xF));
|
||||
P0M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x10 == (pin&0xF0)) //P1
|
||||
{
|
||||
P1M1 |= (1<<(pin&0xF));
|
||||
P1M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x20 == (pin&0xF0)) //P2
|
||||
{
|
||||
P2M1 |= (1<<(pin&0xF));
|
||||
P2M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
|
||||
if(0x30 == (pin&0xF0)) //P3
|
||||
{
|
||||
P3M1 |= (1<<(pin&0xF));
|
||||
P3M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x40 == (pin&0xF0)) //P4
|
||||
{
|
||||
P4M1 |= (1<<(pin&0xF));
|
||||
P4M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x50 == (pin&0xF0)) //P5
|
||||
{
|
||||
P5M1 |= (1<<(pin&0xF));
|
||||
P5M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x60 == (pin&0xF0)) //P5
|
||||
{
|
||||
P6M1 |= (1<<(pin&0xF));
|
||||
P6M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
if(0x70 == (pin&0xF0)) //P5
|
||||
{
|
||||
P7M1 |= (1<<(pin&0xF));
|
||||
P7M0 &= ~(1<<(pin&0xF));
|
||||
}
|
||||
}
|
||||
else if(GPI_OD == mode)
|
||||
{
|
||||
if(0x00 == (pin&0xF0)) //P0
|
||||
{
|
||||
P0M1 |= (1<<(pin&0xF));
|
||||
P0M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x10 == (pin&0xF0)) //P1
|
||||
{
|
||||
P1M1 |= (1<<(pin&0xF));
|
||||
P1M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x20 == (pin&0xF0)) //P2
|
||||
{
|
||||
P2M1 |= (1<<(pin&0xF));
|
||||
P2M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
|
||||
if(0x30 == (pin&0xF0)) //P3
|
||||
{
|
||||
P3M1 |= (1<<(pin&0xF));
|
||||
P3M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x40 == (pin&0xF0)) //P4
|
||||
{
|
||||
P4M1 |= (1<<(pin&0xF));
|
||||
P4M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x50 == (pin&0xF0)) //P5
|
||||
{
|
||||
P5M1 |= (1<<(pin&0xF));
|
||||
P5M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x60 == (pin&0xF0)) //P5
|
||||
{
|
||||
P6M1 |= (1<<(pin&0xF));
|
||||
P6M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
if(0x70 == (pin&0xF0)) //P5
|
||||
{
|
||||
P7M1 |= (1<<(pin&0xF));
|
||||
P7M0 |= (1<<(pin&0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
91
Source/hx711.c
Normal file
91
Source/hx711.c
Normal file
@@ -0,0 +1,91 @@
|
||||
#include "hx711.h"
|
||||
#include "gpio.h"
|
||||
|
||||
uint32 hx711_last_read_value[10];
|
||||
|
||||
void hx711_init()
|
||||
{
|
||||
gpio_mode(HX711_DT_PIN, GPIO); // 设置DT引脚为推挽输出
|
||||
gpio_mode(HX711_SCK_PIN, GPIO); // 设置SCK引脚为推挽输出
|
||||
gpio_set_level(HX711_SCK_PIN, 0); // 初始化SCK为低电平
|
||||
gpio_set_level(HX711_DT_PIN, 1); // 初始化DT为高电平
|
||||
}
|
||||
|
||||
uint32 hx711_read_set(HX711_ch_enum next_ch,uint8 avg_times)
|
||||
{
|
||||
uint32 result = 0;
|
||||
uint8 i;
|
||||
|
||||
if(avg_times > 10) /* 限制平均次数最大值为10 */
|
||||
{
|
||||
avg_times = 10;
|
||||
}
|
||||
gpio_set_level(HX711_SCK_PIN, 0); /* SCK低电平开始读数据 */
|
||||
gpio_set_level(HX711_DT_PIN, 1); /* 确保DT高电平,等待HX711准备好数据 */
|
||||
while(gpio_get_level(HX711_DT_PIN) == 1); /* 等待HX711准备好数据 */
|
||||
for(i = 0; i < 24; i++)
|
||||
{
|
||||
gpio_set_level(HX711_SCK_PIN, 1); /* SCK高电平 */
|
||||
result <<= 1; /* 左移一位 */
|
||||
if(gpio_get_level(HX711_DT_PIN) == 1)
|
||||
{
|
||||
result |= 0x01; /* 如果DT为高电平,设置最低位为1 */
|
||||
}
|
||||
gpio_set_level(HX711_SCK_PIN, 0); /* SCK低电平 */
|
||||
}
|
||||
for(i = 0; i < next_ch; i++)
|
||||
{
|
||||
gpio_set_level(HX711_SCK_PIN, 1); /* SCK高电平 */
|
||||
_nop_();
|
||||
_nop_();
|
||||
gpio_set_level(HX711_SCK_PIN, 0); /* SCK低电平 */
|
||||
}
|
||||
for(i = 0; i < 9; i++)
|
||||
{
|
||||
hx711_last_read_value[i] = hx711_last_read_value[i + 1]; /* 将之前的读取值向前移动 */
|
||||
}
|
||||
hx711_last_read_value[9] = result; /* 将当前读取的值存入最后一个位置 */
|
||||
result = 0;
|
||||
for(i = 0; i < avg_times; i++)
|
||||
{
|
||||
result += hx711_last_read_value[i]/avg_times; /* 累加读取的值 */
|
||||
}
|
||||
|
||||
return result; /* 返回读取到的数据 */
|
||||
}
|
||||
|
||||
|
||||
uint8 hx711_single_read_non_blocking(HX711_ch_enum next_ch)
|
||||
{
|
||||
uint32 result = 0;
|
||||
uint8 i;
|
||||
gpio_set_level(HX711_SCK_PIN, 0); /* SCK低电平开始读数据 */
|
||||
gpio_set_level(HX711_DT_PIN, 1); /* 确保DT高电平,等待HX711准备好数据 */
|
||||
if(gpio_get_level(HX711_DT_PIN) == 1)
|
||||
{
|
||||
return 0; /* 如果DT为高电平,表示HX711未准备好数据 */
|
||||
}
|
||||
for(i = 0; i < 24; i++)
|
||||
{
|
||||
gpio_set_level(HX711_SCK_PIN, 1); /* SCK高电平 */
|
||||
result <<= 1; /* 左移一位 */
|
||||
if(gpio_get_level(HX711_DT_PIN) == 1)
|
||||
{
|
||||
result |= 0x01; /* 如果DT为高电平,设置最低位为1 */
|
||||
}
|
||||
gpio_set_level(HX711_SCK_PIN, 0); /* SCK低电平 */
|
||||
}
|
||||
for(i = 0; i < next_ch; i++)
|
||||
{
|
||||
gpio_set_level(HX711_SCK_PIN, 1); /* SCK高电平 */
|
||||
_nop_();
|
||||
_nop_();
|
||||
gpio_set_level(HX711_SCK_PIN, 0); /* SCK低电平 */
|
||||
}
|
||||
for(i = 0; i < 9; i++)
|
||||
{
|
||||
hx711_last_read_value[i] = hx711_last_read_value[i + 1]; /* 将之前的读取值向前移动 */
|
||||
}
|
||||
hx711_last_read_value[9] = result; /* 将当前读取的值存入最后一个位置 */
|
||||
return 1;
|
||||
}
|
||||
349
Source/iic.c
Normal file
349
Source/iic.c
Normal file
@@ -0,0 +1,349 @@
|
||||
#include "iic.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 内部使用用户无需关心
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void iic_delay_us(uint16 x) //33.1776Mhz
|
||||
{
|
||||
uint8 i;
|
||||
while(x--)
|
||||
{
|
||||
i = 9;
|
||||
while (--i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 内部使用用户无需关心
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint8 wait(void)
|
||||
{
|
||||
uint16 count = 0;
|
||||
uint8 ret = IIC_SEND_OK;
|
||||
while (!(I2CMSST & 0x40))
|
||||
{
|
||||
iic_delay_us(1);
|
||||
if(count++ >= 30)//等待超过30us,则退出等待。
|
||||
{
|
||||
ret = IIC_SEND_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
I2CMSST &= ~0x40;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 内部使用用户无需关心
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint8 start(void)
|
||||
{
|
||||
uint8 ret;
|
||||
I2CMSCR = 0x01; //发送start命令
|
||||
ret = wait();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 内部使用用户无需关心
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint8 send_data(char dat)
|
||||
{
|
||||
uint8 ret;
|
||||
I2CTXD = dat; //写数据到数据缓冲区
|
||||
I2CMSCR = 0x02; //发送SEND命令
|
||||
ret = wait();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 内部使用用户无需关心
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint8 recv_ack(void)
|
||||
{
|
||||
uint8 ret;
|
||||
I2CMSCR = 0x03; //发送读ACK命令
|
||||
ret = wait();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 内部使用用户无需关心
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
char recv_data(void) //接收数据
|
||||
{
|
||||
I2CMSCR = 0x04; //发送RECV命令
|
||||
wait();
|
||||
return I2CRXD;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 内部使用用户无需关心
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint8 send_ack(void)
|
||||
{
|
||||
uint8 ret;
|
||||
I2CMSST = 0x00; //设置ACK信号
|
||||
I2CMSCR = 0x05; //发送ACK命令
|
||||
ret = wait();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 内部使用用户无需关心
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void send_nak(void)
|
||||
{
|
||||
I2CMSST = 0x01; //设置NAK信号
|
||||
I2CMSCR = 0x05; //发送ACK命令
|
||||
wait();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 内部使用用户无需关心
|
||||
// @param NULL
|
||||
// @return void
|
||||
// Sample usage: 无需用户调用,用户请使用h文件中的宏定义
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint8 stop(void)
|
||||
{
|
||||
uint8 ret;
|
||||
I2CMSCR = 0x06; //发送stop命令
|
||||
ret = wait();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//#define UNUSED(expr1, expr2) do { if(scl_pin == sda_pin); } while (0)
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 硬件IIC初始化
|
||||
// @param iic_n 选择IIC模块
|
||||
// @param wait_time I2C总线速度(等待时钟数)控制: 速度设置为等待wait_time*2+1个时钟
|
||||
// @return void
|
||||
// Sample usage:
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void iic_init(IICN_enum iic_n, uint8 wait_time)
|
||||
{
|
||||
//UNUSED(scl_pin);
|
||||
//__attribute__ ((unused))(sda_pin);
|
||||
//UNUSED(scl_pin, sda_pin);
|
||||
|
||||
P_SW2 &= ~(0x03<<4);
|
||||
P_SW2 |= 1<<7; //将EAXFR寄存器置1,这样才能使用特殊功能寄存器为扩展SFR,访问逻辑地址位于 XDATA 区域
|
||||
switch(iic_n)
|
||||
{
|
||||
case IIC_1:
|
||||
P_SW2 |= (0x00<<4); //SCL:P1.5 SDA:P1.4
|
||||
break;
|
||||
case IIC_2:
|
||||
P_SW2 |= (0x01<<4); //SCL:P2.5 SDA:P2.4
|
||||
break;
|
||||
case IIC_3:
|
||||
P_SW2 |= (0x02<<4); //SCL:P7.7 SDA:P7.6
|
||||
break;
|
||||
case IIC_4:
|
||||
P_SW2 |= (0x03<<4); //SCL:P3.2 SDA:P3.3
|
||||
break;
|
||||
}
|
||||
|
||||
I2CCFG |= 1<<6; //主机模式
|
||||
I2CCFG |= 1<<7; //使能IIC
|
||||
I2CCFG |= wait_time&0x3F;//速度设置为等待wait_time*2+1个时钟
|
||||
I2CMSST = 0x00; //主机状态寄存器
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 写入一个字节数据到I2C设备指定寄存器地址
|
||||
// @param iic_n IIC模块(IIC_1,IIC_2,IIC_3,IIC_0)
|
||||
// @param slaveid 从机地址(7位地址)
|
||||
// @param reg 从机寄存器地址
|
||||
// @param dat 需要发送的数据
|
||||
// @return 返回的状态值 0:成功 1:失败
|
||||
// @since v2.0
|
||||
// Sample usage: iic_write_reg(0x2D, 0x50,2); //写入数据2到0x50地址,从机地址为0x2D
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint8 iic_write_reg(uint8 dev_add, uint8 reg, uint8 dat)
|
||||
{
|
||||
if(start() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(send_data((dev_add<<1) | 0x00) != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(recv_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(send_data(reg) != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(recv_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(send_data(dat) != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(recv_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(stop() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
|
||||
return IIC_SEND_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 读取I2C设备指定地址寄存器的数据
|
||||
// @param iic_n I2C通道号及引脚
|
||||
// @param dev_add 从机地址(7位地址)
|
||||
// @param reg 从机寄存器地址
|
||||
// @param dat 数据地址
|
||||
// @return 读取的寄存器值
|
||||
// @since v1.0
|
||||
// Sample usage: uint8 value = iic_read_reg(i2c0, 0x2D, 0x50);//读取0x50地址的数据,从机地址为0x2D
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint8 iic_read_reg(uint8 dev_add, uint8 reg, uint8 *dat)
|
||||
{
|
||||
if(start() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
if(send_data((dev_add<<1) | 0x00) != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(recv_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
if(send_data(reg) != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(recv_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
|
||||
// if(start() != IIC_SEND_OK)
|
||||
// return IIC_SEND_FAIL;
|
||||
|
||||
if(send_data((dev_add<<1) | 0x01) != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
if(recv_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
|
||||
*dat = recv_data(); //读取数据
|
||||
|
||||
|
||||
if(send_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
if(stop() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
return IIC_SEND_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 读取I2C设备指定地址寄存器的数据
|
||||
// @param iic_n I2C通道号及引脚
|
||||
// @param dev_add 从机地址(7位地址)
|
||||
// @param reg 从机寄存器地址
|
||||
// @param dat 读取的数据存储的地址
|
||||
// @param num 读取字节数
|
||||
// @return void
|
||||
// @since v1.0
|
||||
// Sample usage: uint8 value = i2c_read_reg(i2c0, 0x2D, 0x50, 10, buf);//读取0x50地址的数据,从机地址为0x2D开始的10个字节
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint8 iic_read_reg_bytes(uint8 dev_add, uint8 reg
|
||||
, uint8 *dat, uint8 num)
|
||||
{
|
||||
|
||||
if(start() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
if(send_data((dev_add<<1) | 0x00) != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(recv_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
if(send_data(reg) != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(recv_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
if(send_data((dev_add<<1) | 0x01) != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
if(recv_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
while(--num)
|
||||
{
|
||||
*dat = recv_data(); //读取数据
|
||||
if(send_ack() != IIC_SEND_OK)
|
||||
{
|
||||
return IIC_SEND_FAIL;
|
||||
}
|
||||
dat++;
|
||||
}
|
||||
|
||||
*dat = recv_data();
|
||||
|
||||
if(send_ack() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
if(stop() != IIC_SEND_OK)
|
||||
return IIC_SEND_FAIL;
|
||||
|
||||
return IIC_SEND_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 硬件IIC引脚切换函数
|
||||
// @param iic_n I2C通道号及引脚
|
||||
// @param scl_pin 选择SCL引脚
|
||||
// @param sda_pin 选择SDA引脚
|
||||
// Sample usage:
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void iic_change_pin(IICN_enum iic_n)
|
||||
{
|
||||
P_SW2 |= 1<<7; //将EAXFR寄存器置1,这样才能使用特殊功能寄存器为扩展SFR,访问逻辑地址位于 XDATA 区域
|
||||
|
||||
P_SW2 &= ~(0x03<<4); //清除引脚切换位
|
||||
switch(iic_n)
|
||||
{
|
||||
case IIC_1:
|
||||
P_SW2 |= (0x00<<4); //SCL:P1.5 SDA:P1.4
|
||||
break;
|
||||
case IIC_2:
|
||||
P_SW2 |= (0x01<<4); //SCL:P2.5 SDA:P2.4
|
||||
break;
|
||||
case IIC_3:
|
||||
P_SW2 |= (0x02<<4); //SCL:P7.7 SDA:P7.6
|
||||
break;
|
||||
case IIC_4:
|
||||
P_SW2 |= (0x03<<4); //SCL:P3.2 SDA:P3.3
|
||||
break;
|
||||
}
|
||||
|
||||
P_SW2 &= ~(1<<7);
|
||||
|
||||
}
|
||||
134
Source/iic_soft.c
Normal file
134
Source/iic_soft.c
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "iic_soft.h"
|
||||
|
||||
|
||||
|
||||
void soft_iic_delay(uint16 delay_time)
|
||||
{
|
||||
uint16 i;
|
||||
// 简单的延时函数,可以根据实际需要调整
|
||||
for (i = 0; i < delay_time; i++)
|
||||
{
|
||||
_nop_(); // 空操作,延时
|
||||
}
|
||||
}
|
||||
|
||||
void soft_iic_init(IIC_Soft_Config *config)
|
||||
{
|
||||
// 设置SCL和SDA引脚为推挽输出模式
|
||||
gpio_mode(config->scl_pin, GPIO);
|
||||
gpio_mode(config->sda_pin, GPIO);
|
||||
|
||||
// 初始化SCL和SDA引脚为高电平
|
||||
gpio_set_level(config->scl_pin, 1);
|
||||
gpio_set_level(config->sda_pin, 1);
|
||||
}
|
||||
|
||||
void soft_iic_start(IIC_Soft_Config *config)
|
||||
{
|
||||
gpio_set_level(config->sda_pin, 0); // SDA拉低
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
gpio_set_level(config->scl_pin, 0); // SCL拉低
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
}
|
||||
|
||||
void soft_iic_stop(IIC_Soft_Config *config)
|
||||
{
|
||||
gpio_set_level(config->sda_pin, 0); // SDA拉低
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
gpio_set_level(config->scl_pin, 1); // SCL拉高
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
gpio_set_level(config->sda_pin, 1); // SDA拉高
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
}
|
||||
|
||||
uint8 soft_iic_read(IIC_Soft_Config *config)
|
||||
{
|
||||
uint8 dat = 0,i;
|
||||
gpio_set_level(config->sda_pin, 1); // 设置SDA为输入模式
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
gpio_set_level(config->scl_pin, 1); // SCL拉高
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
if (gpio_get_level(config->sda_pin)) // 读取SDA的状态
|
||||
{
|
||||
dat |= (1 << (7 - i)); // 将读取的位存入dat
|
||||
}
|
||||
gpio_set_level(config->scl_pin, 0); // SCL拉低
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
}
|
||||
return dat;
|
||||
}
|
||||
|
||||
void soft_iic_write(IIC_Soft_Config *config, uint8 dat)
|
||||
{
|
||||
uint8 i;
|
||||
gpio_set_level(config->sda_pin, 0); // 设置SDA为输出模式
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
if (dat & (1 << (7 - i))) // 检查当前位
|
||||
{
|
||||
gpio_set_level(config->sda_pin, 1); // 写入1
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_set_level(config->sda_pin, 0); // 写入0
|
||||
}
|
||||
gpio_set_level(config->scl_pin, 1); // SCL拉高
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
gpio_set_level(config->scl_pin, 0); // SCL拉低
|
||||
}
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
}
|
||||
|
||||
uint8 soft_iic_ack(IIC_Soft_Config *config)
|
||||
{
|
||||
gpio_set_level(config->sda_pin, 0); // 发送ACK
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
gpio_set_level(config->scl_pin, 1); // SCL拉高
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
gpio_set_level(config->scl_pin, 0); // SCL拉低
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
return 0; // 返回ACK成功
|
||||
}
|
||||
|
||||
|
||||
void soft_iic_nack(IIC_Soft_Config *config)
|
||||
{
|
||||
gpio_set_level(config->sda_pin, 1); // 发送NACK
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
gpio_set_level(config->scl_pin, 1); // SCL拉高
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
gpio_set_level(config->scl_pin, 0); // SCL拉低
|
||||
soft_iic_delay(config->wait_time); // 等待一段时间
|
||||
}
|
||||
|
||||
|
||||
|
||||
void soft_iic_write_reg(IIC_Soft_Config *config, uint8 dev_addr, uint8 reg, uint8 dat)
|
||||
{
|
||||
soft_iic_start(config); // 发送起始信号
|
||||
soft_iic_write(config, (dev_addr << 1) | 0); // 发送设备地址和写命令
|
||||
soft_iic_ack(config); // 等待ACK
|
||||
soft_iic_write(config, reg); // 发送寄存器地址
|
||||
soft_iic_ack(config); // 等待ACK
|
||||
soft_iic_write(config, dat); // 发送数据
|
||||
soft_iic_ack(config); // 等待ACK
|
||||
soft_iic_stop(config); // 发送停止信号
|
||||
}
|
||||
|
||||
uint8 soft_iic_read_reg(IIC_Soft_Config *config, uint8 dev_addr, uint8 reg, uint8 *dat)
|
||||
{
|
||||
soft_iic_start(config); // 发送起始信号
|
||||
soft_iic_write(config, (dev_addr << 1) | 0); // 发送设备地址和写命令
|
||||
soft_iic_ack(config); // 等待ACK
|
||||
soft_iic_write(config, reg); // 发送寄存器地址
|
||||
soft_iic_ack(config); // 等待ACK
|
||||
soft_iic_start(config); // 重新发送起始信号
|
||||
soft_iic_write(config, (dev_addr << 1) | 1); // 发送设备地址和读命令
|
||||
soft_iic_ack(config); // 等待ACK
|
||||
*dat = soft_iic_read(config); // 读取数据
|
||||
soft_iic_nack(config); // 发送NACK
|
||||
soft_iic_stop(config); // 发送停止信号
|
||||
return *dat; // 返回读取的数据
|
||||
}
|
||||
172
Source/isr.c
Normal file
172
Source/isr.c
Normal file
@@ -0,0 +1,172 @@
|
||||
#include "isr.h"
|
||||
#include "command.h"
|
||||
|
||||
|
||||
//UART1中断
|
||||
void UART1_Isr() interrupt 4
|
||||
{
|
||||
uint8 res;
|
||||
static uint8 dwon_count;
|
||||
if(UART1_GET_TX_FLAG)
|
||||
{
|
||||
UART1_CLEAR_TX_FLAG;
|
||||
busy[1] = 0;
|
||||
}
|
||||
if(UART1_GET_RX_FLAG)
|
||||
{
|
||||
UART1_CLEAR_RX_FLAG;
|
||||
res = SBUF;
|
||||
//程序自动下载
|
||||
if(res == 0x7F)
|
||||
{
|
||||
if(dwon_count++ > 20)
|
||||
{
|
||||
IAP_CONTR = 0x60;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dwon_count = 0;
|
||||
}
|
||||
command_uart_callback(res);
|
||||
}
|
||||
}
|
||||
|
||||
//UART2中断
|
||||
void UART2_Isr() interrupt 8
|
||||
{
|
||||
if(UART2_GET_TX_FLAG)
|
||||
{
|
||||
UART2_CLEAR_TX_FLAG;
|
||||
busy[2] = 0;
|
||||
}
|
||||
if(UART2_GET_RX_FLAG)
|
||||
{
|
||||
UART2_CLEAR_RX_FLAG;
|
||||
//接收数据寄存器为:S2BUF
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//UART3中断
|
||||
void UART3_Isr() interrupt 17
|
||||
{
|
||||
if(UART3_GET_TX_FLAG)
|
||||
{
|
||||
UART3_CLEAR_TX_FLAG;
|
||||
busy[3] = 0;
|
||||
}
|
||||
if(UART3_GET_RX_FLAG)
|
||||
{
|
||||
UART3_CLEAR_RX_FLAG;
|
||||
//接收数据寄存器为:S3BUF
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//UART4中断
|
||||
void UART4_Isr() interrupt 18
|
||||
{
|
||||
if(UART4_GET_TX_FLAG)
|
||||
{
|
||||
UART4_CLEAR_TX_FLAG;
|
||||
busy[4] = 0;
|
||||
}
|
||||
if(UART4_GET_RX_FLAG)
|
||||
{
|
||||
UART4_CLEAR_RX_FLAG;
|
||||
|
||||
//接收数据寄存器为:S4BUF;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define LED P52
|
||||
void INT0_Isr() interrupt 0
|
||||
{
|
||||
|
||||
}
|
||||
void INT1_Isr() interrupt 2
|
||||
{
|
||||
|
||||
}
|
||||
void INT2_Isr() interrupt 10
|
||||
{
|
||||
INT2_CLEAR_FLAG; //清除中断标志
|
||||
}
|
||||
void INT3_Isr() interrupt 11
|
||||
{
|
||||
INT3_CLEAR_FLAG; //清除中断标志
|
||||
}
|
||||
|
||||
void INT4_Isr() interrupt 16
|
||||
{
|
||||
INT4_CLEAR_FLAG; //清除中断标志
|
||||
}
|
||||
|
||||
void TM0_Isr() interrupt 1
|
||||
{
|
||||
|
||||
}
|
||||
void TM1_Isr() interrupt 3
|
||||
{
|
||||
|
||||
}
|
||||
void TM2_Isr() interrupt 12
|
||||
{
|
||||
TIM2_CLEAR_FLAG; //清除中断标志
|
||||
|
||||
}
|
||||
void TM3_Isr() interrupt 19
|
||||
{
|
||||
TIM3_CLEAR_FLAG; //清除中断标志
|
||||
|
||||
}
|
||||
|
||||
void TM4_Isr() interrupt 20
|
||||
{
|
||||
TIM4_CLEAR_FLAG; //清除中断标志
|
||||
|
||||
}
|
||||
|
||||
// void change_LED();
|
||||
|
||||
void P0_ISR() interrupt P0INT_VECTOR
|
||||
{
|
||||
if(P0INTF & 0x10) //P0.4
|
||||
{
|
||||
P0INTF &= ~0x10;
|
||||
|
||||
}
|
||||
if(P0INTF & 0x20) //P0.5
|
||||
{
|
||||
P0INTF &= ~0x20;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//void INT0_Isr() interrupt 0;
|
||||
//void TM0_Isr() interrupt 1;
|
||||
//void INT1_Isr() interrupt 2;
|
||||
//void TM1_Isr() interrupt 3;
|
||||
//void UART1_Isr() interrupt 4;
|
||||
//void ADC_Isr() interrupt 5;
|
||||
//void LVD_Isr() interrupt 6;
|
||||
//void PCA_Isr() interrupt 7;
|
||||
//void UART2_Isr() interrupt 8;
|
||||
//void SPI_Isr() interrupt 9;
|
||||
//void INT2_Isr() interrupt 10;
|
||||
//void INT3_Isr() interrupt 11;
|
||||
//void TM2_Isr() interrupt 12;
|
||||
//void INT4_Isr() interrupt 16;
|
||||
//void UART3_Isr() interrupt 17;
|
||||
//void UART4_Isr() interrupt 18;
|
||||
//void TM3_Isr() interrupt 19;
|
||||
//void TM4_Isr() interrupt 20;
|
||||
//void CMP_Isr() interrupt 21;
|
||||
//void I2C_Isr() interrupt 24;
|
||||
//void USB_Isr() interrupt 25;
|
||||
//void PWM1_Isr() interrupt 26;
|
||||
//void PWM2_Isr() interrupt 27;
|
||||
18
Source/main.c
Normal file
18
Source/main.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "common.h"
|
||||
#include "delay.h"
|
||||
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
board_init(); // 初始化板子
|
||||
delay_ms(1000);
|
||||
printf("System Init...\r\n");
|
||||
|
||||
while(1)
|
||||
{
|
||||
delay_ms(1000);
|
||||
printf("System Running...\r\n");
|
||||
}
|
||||
}
|
||||
437
Source/pwm.c
Normal file
437
Source/pwm.c
Normal file
@@ -0,0 +1,437 @@
|
||||
#include "pwm.h"
|
||||
#include "gpio.h"
|
||||
|
||||
//捕获比较模式寄存器
|
||||
const uint32 PWM_CCMR_ADDR[] = {0x7efec8, 0x7efec9, 0x7efeca ,0x7efecb,
|
||||
0x7efee8, 0x7efee9, 0x7efeea, 0x7efeeb};
|
||||
//捕获比较使能寄存器
|
||||
const uint32 PWM_CCER_ADDR[] = {0x7efecc, 0x7efecd,
|
||||
0x7efeec ,0x7efeed};
|
||||
//控制寄存器,高8位地址 低8位地址 + 1即可
|
||||
const uint32 PWM_CCR_ADDR[] = {0x7efed5, 0x7efed7, 0x7efed9, 0x7efedb,
|
||||
0x7efef5, 0x7efef7, 0x7efef9, 0x7efefb};
|
||||
|
||||
//控制寄存器,高8位地址 低8位地址 + 1即可
|
||||
const uint32 PWM_ARR_ADDR[] = {0x7efed2,0x7efef2};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief PWM_gpio初始化(内部使用用户无需关心)
|
||||
// @param pwmch PWM通道号及引脚
|
||||
// @return void
|
||||
// Sample usage:
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void pwm_set_gpio(PWMCH_enum pwmch)
|
||||
{
|
||||
switch(pwmch)
|
||||
{
|
||||
case PWMA_CH1P_P10:
|
||||
{
|
||||
gpio_mode(P1_0,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH1N_P11:
|
||||
{
|
||||
gpio_mode(P1_1,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH1P_P20:
|
||||
{
|
||||
gpio_mode(P2_0,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH1N_P21:
|
||||
{
|
||||
gpio_mode(P2_1,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH1P_P60:
|
||||
{
|
||||
gpio_mode(P6_0,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH1N_P61:
|
||||
{
|
||||
gpio_mode(P6_1,GPO_PP);
|
||||
break;
|
||||
}
|
||||
|
||||
case PWMA_CH2P_P12:
|
||||
{
|
||||
gpio_mode(P1_2,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH2N_P13:
|
||||
{
|
||||
gpio_mode(P1_3,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH2P_P22:
|
||||
{
|
||||
gpio_mode(P2_2,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH2N_P23:
|
||||
{
|
||||
gpio_mode(P2_3,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH2P_P62:
|
||||
{
|
||||
gpio_mode(P6_2,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH2N_P63:
|
||||
{
|
||||
gpio_mode(P6_3,GPO_PP);
|
||||
break;
|
||||
}
|
||||
|
||||
case PWMA_CH3P_P14:
|
||||
{
|
||||
gpio_mode(P1_4,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH3N_P15:
|
||||
{
|
||||
gpio_mode(P1_5,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH3P_P24:
|
||||
{
|
||||
gpio_mode(P2_4,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH3N_P25:
|
||||
{
|
||||
gpio_mode(P2_5,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH3P_P64:
|
||||
{
|
||||
gpio_mode(P6_4,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH3N_P65:
|
||||
{
|
||||
gpio_mode(P6_5,GPO_PP);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case PWMA_CH4P_P16:
|
||||
{
|
||||
gpio_mode(P1_6,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH4N_P17:
|
||||
{
|
||||
gpio_mode(P1_7,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH4P_P26:
|
||||
{
|
||||
gpio_mode(P2_6,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH4N_P27:
|
||||
{
|
||||
gpio_mode(P2_7,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH4P_P66:
|
||||
{
|
||||
gpio_mode(P6_6,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH4N_P67:
|
||||
{
|
||||
gpio_mode(P6_7,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH4P_P34:
|
||||
{
|
||||
gpio_mode(P3_4,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMA_CH4N_P33:
|
||||
{
|
||||
gpio_mode(P3_3,GPO_PP);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case PWMB_CH1_P20:
|
||||
{
|
||||
gpio_mode(P2_0,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH1_P17:
|
||||
{
|
||||
gpio_mode(P1_7,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH1_P00:
|
||||
{
|
||||
gpio_mode(P0_0,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH1_P74:
|
||||
{
|
||||
gpio_mode(P7_4,GPO_PP);
|
||||
break;
|
||||
}
|
||||
|
||||
case PWMB_CH2_P21:
|
||||
{
|
||||
gpio_mode(P2_1,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH2_P54:
|
||||
{
|
||||
gpio_mode(P5_4,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH2_P01:
|
||||
{
|
||||
gpio_mode(P0_1,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH2_P75:
|
||||
{
|
||||
gpio_mode(P7_5,GPO_PP);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case PWMB_CH3_P22:
|
||||
{
|
||||
gpio_mode(P2_2,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH3_P33:
|
||||
{
|
||||
gpio_mode(P3_3,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH3_P02:
|
||||
{
|
||||
gpio_mode(P0_2,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH3_P76:
|
||||
{
|
||||
gpio_mode(P7_6,GPO_PP);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case PWMB_CH4_P23:
|
||||
{
|
||||
gpio_mode(P2_3,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH4_P34:
|
||||
{
|
||||
gpio_mode(P3_4,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH4_P03:
|
||||
{
|
||||
gpio_mode(P0_3,GPO_PP);
|
||||
break;
|
||||
}
|
||||
case PWMB_CH4_P77:
|
||||
{
|
||||
gpio_mode(P7_7,GPO_PP);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief PWM初始化
|
||||
// @param pwmch PWM通道号及引脚
|
||||
// @param freq PWM频率(10Hz-3MHz)
|
||||
// @param duty PWM占空比
|
||||
// @return void
|
||||
// Sample usage:
|
||||
// pwm_init(PWM0_P00, 100, 5000); //初始化PWM0 使用引脚P0.0 输出PWM频率100HZ 占空比为百分之 5000/PWM_DUTY_MAX*100
|
||||
// PWM_DUTY_MAX在zf_pwm.h文件中 默认为10000
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void pwm_init(PWMCH_enum pwmch,uint32 freq, uint32 duty)
|
||||
{
|
||||
|
||||
uint32 match_temp;
|
||||
uint32 period_temp;
|
||||
uint16 freq_div = 0;
|
||||
|
||||
|
||||
P_SW2 |= 0x80;
|
||||
|
||||
//GPIO需要设置为推挽输出
|
||||
pwm_set_gpio(pwmch);
|
||||
|
||||
|
||||
//分频计算,周期计算,占空比计算
|
||||
freq_div = (sys_clk / freq) >> 16; //多少分频
|
||||
period_temp = sys_clk / freq ;
|
||||
period_temp = period_temp / (freq_div + 1) - 1; //周期
|
||||
|
||||
if(duty != PWM_DUTY_MAX)
|
||||
{
|
||||
match_temp = period_temp * ((float)duty / PWM_DUTY_MAX); // 占空比
|
||||
}
|
||||
else
|
||||
{
|
||||
match_temp = period_temp + 1; // duty为100%
|
||||
}
|
||||
|
||||
|
||||
if(PWMB_CH1_P20 <= pwmch) //PWM5-8
|
||||
{
|
||||
//通道选择,引脚选择
|
||||
PWMB_ENO |= (1 << ((2 * ((pwmch >> 4) - 4)))); //使能通道
|
||||
PWMB_PS |= ((pwmch & 0x03) << ((2 * ((pwmch >> 4) - 4)))); //输出脚选择
|
||||
|
||||
// 配置通道输出使能和极性
|
||||
(*(unsigned char volatile far *) (PWM_CCER_ADDR[pwmch>>5])) |= (uint8)(1 << (((pwmch >> 4) & 0x01) * 4));
|
||||
|
||||
//设置预分频
|
||||
PWMB_PSCRH = (uint8)(freq_div>>8);
|
||||
PWMB_PSCRL = (uint8)freq_div;
|
||||
|
||||
PWMB_BKR = 0x80; //主输出使能 相当于总开关
|
||||
PWMB_CR1 = 0x01; //PWM开始计数
|
||||
}
|
||||
else
|
||||
{
|
||||
PWMA_ENO |= (1 << (pwmch & 0x01)) << ((pwmch >> 4) * 2); //使能通道
|
||||
PWMA_PS |= ((pwmch & 0x07) >> 1) << ((pwmch >> 4) * 2); //输出脚选择
|
||||
|
||||
// 配置通道输出使能和极性
|
||||
(*(unsigned char volatile far *) (PWM_CCER_ADDR[pwmch>>5])) |= (1 << ((pwmch & 0x01) * 2 + ((pwmch >> 4) & 0x01) * 0x04));
|
||||
|
||||
|
||||
//设置预分频
|
||||
PWMA_PSCRH = (uint8)(freq_div>>8);
|
||||
PWMA_PSCRL = (uint8)freq_div;
|
||||
|
||||
PWMA_BKR = 0x80; // 主输出使能 相当于总开关
|
||||
PWMA_CR1 = 0x01; //PWM开始计数
|
||||
}
|
||||
|
||||
//周期
|
||||
(*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6])) = (uint8)(period_temp>>8); //高8位
|
||||
(*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6] + 1)) = (uint8)period_temp; //低8位
|
||||
|
||||
//设置捕获值|比较值
|
||||
(*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4])) = match_temp>>8; //高8位
|
||||
(*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4] + 1)) = (uint8)match_temp; //低8位
|
||||
|
||||
//功能设置
|
||||
(*(unsigned char volatile far *) (PWM_CCMR_ADDR[pwmch>>4])) |= 0x06<<4; //设置为PWM模式1
|
||||
(*(unsigned char volatile far *) (PWM_CCMR_ADDR[pwmch>>4])) |= 1<<3; //开启PWM寄存器的预装载功
|
||||
|
||||
|
||||
// P_SW2 &= 0x7F;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief PWM占空比设置
|
||||
// @param pwmch PWM通道号及引脚
|
||||
// @param duty PWM占空比
|
||||
// @return void
|
||||
// Sample usage: pwm_duty(PWM0_P00, 5000); //初始化PWM0 使用引脚P0.0 输出PWM频率50HZ 占空比为百分之 5000/PWM_DUTY_MAX*100
|
||||
// PWM_DUTY_MAX在fsl_pwm.h文件中 默认为10000
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void pwm_duty(PWMCH_enum pwmch, uint32 duty)
|
||||
{
|
||||
uint32 match_temp;
|
||||
uint32 arr = ((*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6]))<<8) | (*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6] + 1 ));
|
||||
|
||||
// P_SW2 |= 0x80;
|
||||
|
||||
if(duty != PWM_DUTY_MAX)
|
||||
{
|
||||
match_temp = arr * ((float)duty/PWM_DUTY_MAX); //占空比
|
||||
}
|
||||
else
|
||||
{
|
||||
match_temp = arr + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//设置捕获值|比较值
|
||||
(*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4])) = match_temp>>8; //高8位
|
||||
(*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4] + 1)) = (uint8)match_temp; //低8位
|
||||
|
||||
// P_SW2 &= ~0x80;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief PWM频率设置
|
||||
// @param pwmch PWM通道号及引脚
|
||||
// @param freq PWM频率(10Hz-3MHz)
|
||||
// @param duty PWM占空比
|
||||
// @return void
|
||||
// Sample usage: pwm_freq(PWM0_P00, 50, 5000); //修改化PWM0 使用引脚P0.0 输出PWM频率50HZ 占空比为百分之 5000/PWM_DUTY_MAX*100
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void pwm_freq(PWMCH_enum pwmch, uint32 freq, uint32 duty)
|
||||
{
|
||||
uint32 match_temp;
|
||||
uint32 period_temp;
|
||||
uint16 freq_div = 0;
|
||||
|
||||
|
||||
|
||||
//分频计算,周期计算,占空比计算
|
||||
freq_div = (sys_clk / freq) >> 16; // 多少分频
|
||||
period_temp = sys_clk / freq;
|
||||
period_temp = period_temp / (freq_div + 1) - 1; // 周期
|
||||
|
||||
if(duty != PWM_DUTY_MAX)
|
||||
{
|
||||
match_temp = period_temp * ((float)duty / PWM_DUTY_MAX); // 占空比
|
||||
}
|
||||
else
|
||||
{
|
||||
match_temp = period_temp + 1; // duty为100%
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// P_SW2 |= 0x80;
|
||||
|
||||
if(PWMB_CH1_P20 <= pwmch) //PWM5-8
|
||||
{
|
||||
//设置预分频
|
||||
PWMB_PSCRH = (uint8)(freq_div>>8);
|
||||
PWMB_PSCRL = (uint8)freq_div;
|
||||
}
|
||||
else
|
||||
{
|
||||
//设置预分频
|
||||
PWMA_PSCRH = (uint8)(freq_div>>8);
|
||||
PWMA_PSCRL = (uint8)freq_div;
|
||||
}
|
||||
|
||||
//周期
|
||||
(*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6])) = (uint8)(period_temp>>8); //高8位
|
||||
(*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6] + 1)) = (uint8)period_temp; //低8位
|
||||
|
||||
//设置捕获值|比较值
|
||||
(*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4])) = match_temp>>8; //高8位
|
||||
(*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4] + 1)) = (uint8)match_temp; //低8位
|
||||
|
||||
// P_SW2 &= ~0x80;
|
||||
}
|
||||
|
||||
|
||||
24
Source/stc32_stc8_usb.c
Normal file
24
Source/stc32_stc8_usb.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "stc32_stc8_usb.h"
|
||||
|
||||
char *USER_DEVICEDESC = NULL;
|
||||
char *USER_PRODUCTDESC = NULL;
|
||||
char *USER_STCISPCMD = "@STCISP#";
|
||||
|
||||
|
||||
/************************************************
|
||||
函数功能:USB-CDC串口接收数据的回调函数
|
||||
函数描述:回调函数由USB中断在接收到串口数据时自动调用
|
||||
回调函数处理完成串口数据后需要返回1
|
||||
函数返回:返回1:USB中断服务程序自动完成后续的收尾工作
|
||||
返回0:USB会暂停接收串口数据,直到用户自行调用
|
||||
usb_OUT_done()函数后USB才会重新恢复接收数据
|
||||
注意事项:当函数返回1时用户无需调用usb_OUT_done()
|
||||
只有返回0时才需要调用usb_OUT_done()进行手动收尾
|
||||
强烈建议usb_OUT_callback返回1
|
||||
************************************************/
|
||||
BOOL usb_OUT_callback()
|
||||
{
|
||||
USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
|
||||
|
||||
return 1;
|
||||
}
|
||||
218
Source/tim.c
Normal file
218
Source/tim.c
Normal file
@@ -0,0 +1,218 @@
|
||||
#include "tim.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 定时器初始化作为外部计数
|
||||
// @param tim_n 选择模块
|
||||
// @return void
|
||||
// @since v1.0
|
||||
// Sample usage: ctimer_count_init(CTIM0_P34); //初始化定时器0,外部输入为P3.4引脚
|
||||
// @note 串口1使用定时器1作为波特率发生器,
|
||||
// 串口2使用定时器2作为波特率发生器,
|
||||
// 串口3使用定时器3作为波特率发生器,
|
||||
// 串口4使用定时器4作为波特率发生器,
|
||||
// STC16F仅有定时器0-定时器4,这5个定时器。
|
||||
// 编码器采集数据也需要定时器作为外部计数。
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void ctimer_count_init(CTIMN_enum tim_n)
|
||||
{
|
||||
|
||||
switch(tim_n)
|
||||
{
|
||||
case CTIM0_P34:
|
||||
{
|
||||
TL0 = 0;
|
||||
TH0 = 0;
|
||||
TMOD |= 0x04; //外部计数模式
|
||||
TR0 = 1; //启动定时器
|
||||
break;
|
||||
}
|
||||
|
||||
case CTIM1_P35:
|
||||
{
|
||||
TL1 = 0x00;
|
||||
TH1 = 0x00;
|
||||
TMOD |= 0x40; // 外部计数模式
|
||||
TR1 = 1; // 启动定时器
|
||||
break;
|
||||
}
|
||||
|
||||
case CTIM2_P12:
|
||||
{
|
||||
T2L = 0x00;
|
||||
T2H = 0x00;
|
||||
AUXR |= 0x18; // 设置外部计数模式并启动定时器
|
||||
break;
|
||||
}
|
||||
|
||||
case CTIM3_P04:
|
||||
{
|
||||
T3L = 0;
|
||||
T3H = 0;
|
||||
T4T3M |= 0x0c; // 设置外部计数模式并启动定时器
|
||||
break;
|
||||
}
|
||||
|
||||
case CTIM4_P06:
|
||||
{
|
||||
T4L = 0;
|
||||
T4H = 0;
|
||||
T4T3M |= 0xc0; // 设置外部计数模式并启动定时器
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 获取计数数值
|
||||
// @param countch 计数通道号及引脚
|
||||
// @return uint32 返回计数值
|
||||
// Sample usage: num = ctimer_count_read(CTIM0_P34);
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
uint16 ctimer_count_read(CTIMN_enum tim_n)
|
||||
{
|
||||
uint16 dat = 0;
|
||||
|
||||
switch(tim_n)
|
||||
{
|
||||
case CTIM0_P34:
|
||||
{
|
||||
dat = (uint16)TH0 << 8;
|
||||
dat = ((uint8)TL0) | dat;
|
||||
break;
|
||||
}
|
||||
case CTIM1_P35:
|
||||
{
|
||||
dat = (uint16)TH1 << 8;
|
||||
dat = ((uint8)TL1) | dat;
|
||||
break;
|
||||
}
|
||||
case CTIM2_P12:
|
||||
{
|
||||
dat = (uint16)T2H << 8;
|
||||
dat = ((uint8)T2L) | dat;
|
||||
break;
|
||||
}
|
||||
case CTIM3_P04:
|
||||
{
|
||||
dat = (uint16)T3H << 8;
|
||||
dat = ((uint8)T3L) | dat;
|
||||
break;
|
||||
}
|
||||
case CTIM4_P06:
|
||||
{
|
||||
dat = (uint16)T4H << 8;
|
||||
dat = ((uint8)T4L) | dat;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return dat;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 清除计数数值
|
||||
// @param countch 计数通道号及引脚
|
||||
// @return void
|
||||
// Sample usage: ctimer_count_clean(CTIM0_P34);
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void ctimer_count_clean(CTIMN_enum tim_n)
|
||||
{
|
||||
switch(tim_n)
|
||||
{
|
||||
case CTIM0_P34:
|
||||
{
|
||||
TR0 = 0;
|
||||
TH0 = 0;
|
||||
TL0 = 0;
|
||||
TR0 = 1;
|
||||
break;
|
||||
}
|
||||
case CTIM1_P35:
|
||||
{
|
||||
TR1 = 0;
|
||||
TH1 = 0;
|
||||
TL1 = 0;
|
||||
TR1 = 1;
|
||||
break;
|
||||
}
|
||||
case CTIM2_P12:
|
||||
{
|
||||
AUXR &= ~(1<<4);
|
||||
T2H = 0;
|
||||
T2L = 0;
|
||||
AUXR |= 1<<4;
|
||||
break;
|
||||
}
|
||||
case CTIM3_P04:
|
||||
{
|
||||
T4T3M &= ~(1<<3);
|
||||
T3H = 0;
|
||||
T3L = 0;
|
||||
T4T3M |= (1<<3);
|
||||
break;
|
||||
}
|
||||
case CTIM4_P06:
|
||||
{
|
||||
T4T3M &= ~(1<<7);
|
||||
T4H = 0;
|
||||
T4L = 0;
|
||||
T4T3M |= (1<<7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 定时器周期中断
|
||||
// @param tim_n 定时器通道号
|
||||
// @param time_ms 时间(ms)
|
||||
// @return void
|
||||
// Sample usage: pit_timer_ms(TIM_0, 10)
|
||||
// 使用定时器0做周期中断,时间10ms一次。
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void pit_timer_ms(TIMN_enum tim_n,uint16 time_ms)
|
||||
{
|
||||
uint16 temp;
|
||||
temp = (uint16)65536 - (uint16)(sys_clk / (12 * (1000 / time_ms)));
|
||||
|
||||
if(TIM_0 == tim_n)
|
||||
{
|
||||
TMOD |= 0x00; // 模式 0
|
||||
TL0 = temp;
|
||||
TH0 = temp >> 8;
|
||||
TR0 = 1; // 启动定时器
|
||||
ET0 = 1; // 使能定时器中断
|
||||
}
|
||||
else if(TIM_1 == tim_n)
|
||||
{
|
||||
TMOD |= 0x00; // 模式 0
|
||||
TL1 = temp;
|
||||
TH1 = temp >> 8;
|
||||
TR1 = 1; // 启动定时器
|
||||
ET1 = 1; // 使能定时器中断
|
||||
}
|
||||
else if(TIM_2 == tim_n)
|
||||
{
|
||||
T2L = temp;
|
||||
T2H = temp >> 8;
|
||||
AUXR |= 0x10; // 启动定时器
|
||||
IE2 |= 0x04; // 使能定时器中断
|
||||
}
|
||||
else if(TIM_3 == tim_n)
|
||||
{
|
||||
T3L = temp;
|
||||
T3H = temp >> 8;
|
||||
T4T3M |= 0x08; // 启动定时器
|
||||
IE2 |= 0x20; // 使能定时器中断
|
||||
}
|
||||
else if(TIM_4 == tim_n)
|
||||
{
|
||||
T4L = temp;
|
||||
T4H = temp >> 8;
|
||||
T4T3M |= 0x80; // 启动定时器
|
||||
IE2 |= 0x40; // 使能定时器中断
|
||||
}
|
||||
}
|
||||
|
||||
229
Source/uart.c
Normal file
229
Source/uart.c
Normal file
@@ -0,0 +1,229 @@
|
||||
#include "uart.h"
|
||||
|
||||
uint8 busy[5]; //接收忙标志位
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 串口初始化
|
||||
// @param uart_n 串口模块号(USART_1,USART_2,USART_3,USART_4)
|
||||
// @param uart_rx_pin 串口接收引脚
|
||||
// @param uart_tx_pin 串口发送引脚
|
||||
// @param baud 串口波特率
|
||||
// @param tim_n 使用tim_n作为串口波特率发生器(TIM1-TIM4)
|
||||
// @return NULL
|
||||
// Sample usage: uart_init(UART_1, UART1_RX_P30, UART1_TX_P31, 115200, TIM_2); //初始化串口1 波特率115200 发送引脚使用P31 接收引脚使用P30 ,使用定时器2作为波特率发生器
|
||||
// @note 串口1使用 定时器1或者定时器2 作为波特率发生器。
|
||||
// 串口2使用 定时器2 作为波特率发生器。
|
||||
// 串口3使用 定时器3或者定时器2 作为波特率发生器。
|
||||
// 串口4使用 定时器4或者定时器2 作为波特率发生器。
|
||||
// STC32G仅有 定时器0-定时器4,这5个定时器。
|
||||
// 编码器采集数据也需要定时器作为外部计数。
|
||||
// 如果不同的串口,使用同一个定时器,串口的波特率以最后一个初始化为准
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void uart_init(UARTN_enum uart_n, UARTPIN_enum uart_rx_pin, UARTPIN_enum uart_tx_pin, uint32 baud, TIMN_enum tim_n)
|
||||
{
|
||||
uint16 brt;
|
||||
|
||||
brt = (uint16)(65536 - (sys_clk/baud/4));
|
||||
|
||||
|
||||
switch(uart_n)
|
||||
{
|
||||
case UART_1:
|
||||
{
|
||||
if(TIM_1 == tim_n)
|
||||
{
|
||||
SCON |= 0x50;
|
||||
TMOD |= 0x00;
|
||||
TL1 = brt;
|
||||
TH1 = brt >> 8;
|
||||
AUXR |= 0x40;
|
||||
TR1 = 1;
|
||||
busy[1] = 0;
|
||||
}
|
||||
else if(TIM_2 == tim_n)
|
||||
{
|
||||
SCON |= 0x50;
|
||||
T2L = brt;
|
||||
T2H = brt >> 8;
|
||||
AUXR |= 0x15;
|
||||
}
|
||||
P_SW1 &= ~(0x03<<6);
|
||||
if((UART1_RX_P30 == uart_rx_pin) && (UART1_TX_P31 == uart_tx_pin))
|
||||
{
|
||||
P_SW1 |= 0x00;
|
||||
}
|
||||
else if((UART1_RX_P36 == uart_rx_pin) && (UART1_TX_P37 == uart_tx_pin))
|
||||
{
|
||||
P_SW1 |= 0x40;
|
||||
}
|
||||
else if((UART1_RX_P16 == uart_rx_pin) && (UART1_TX_P17 == uart_tx_pin))
|
||||
{
|
||||
P_SW1 |= 0x80;
|
||||
}
|
||||
else if((UART1_RX_P43 == uart_rx_pin) && (UART1_TX_P44 == uart_tx_pin))
|
||||
{
|
||||
P_SW1 |= 0xc0;
|
||||
}
|
||||
busy[1] = 0;
|
||||
ES = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case UART_2:
|
||||
{
|
||||
if(TIM_2 == tim_n)
|
||||
{
|
||||
S2CON |= 0x50;
|
||||
T2L = brt;
|
||||
T2H = brt >> 8;
|
||||
AUXR |= 0x14;
|
||||
}
|
||||
|
||||
P_SW2 &= ~(0x01<<0);
|
||||
if((UART2_RX_P10 == uart_rx_pin) && (UART2_TX_P11 == uart_tx_pin))
|
||||
{
|
||||
P_SW2 |= 0x00;
|
||||
}
|
||||
else if((UART2_RX_P46 == uart_rx_pin) && (UART2_TX_P47 == uart_tx_pin))
|
||||
{
|
||||
P_SW2 |= 0x01;
|
||||
}
|
||||
|
||||
IE2 |= 0x01 << 0; //允许串行口2中断
|
||||
busy[2] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case UART_3:
|
||||
{
|
||||
if(TIM_2 == tim_n)
|
||||
{
|
||||
S3CON |= 0x10;
|
||||
T2L = brt;
|
||||
T2H = brt >> 8;
|
||||
AUXR |= 0x14;
|
||||
}
|
||||
else if(TIM_3 == tim_n)
|
||||
{
|
||||
S3CON |= 0x50;
|
||||
T3L = brt;
|
||||
T3H = brt >> 8;
|
||||
T4T3M |= 0x0a;
|
||||
}
|
||||
|
||||
P_SW2 &= ~(0x01<<1);
|
||||
if((UART3_RX_P00 == uart_rx_pin) && (UART3_TX_P01 == uart_tx_pin))
|
||||
{
|
||||
P_SW2 |= 0x00;
|
||||
}
|
||||
else if((UART3_RX_P50 == uart_rx_pin) && (UART3_TX_P51 == uart_tx_pin))
|
||||
{
|
||||
P_SW2 |= 0x02;
|
||||
}
|
||||
|
||||
IE2 |= 0x01<<3; //允许串行口3中断
|
||||
busy[3] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case UART_4:
|
||||
{
|
||||
if(TIM_2 == tim_n)
|
||||
{
|
||||
S4CON |= 0x10;
|
||||
T2L = brt;
|
||||
T2H = brt >> 8;
|
||||
AUXR |= 0x14;
|
||||
}
|
||||
else if(TIM_4 == tim_n)
|
||||
{
|
||||
S4CON |= 0x50;
|
||||
T4L = brt;
|
||||
T4H = brt >> 8;
|
||||
T4T3M |= 0xa0;
|
||||
}
|
||||
|
||||
P_SW2 &= ~(0x01<<2);
|
||||
if((UART4_RX_P02 == uart_rx_pin) && (UART4_TX_P03 == uart_tx_pin))
|
||||
{
|
||||
P_SW2 |= 0x00;
|
||||
}
|
||||
else if((UART4_RX_P52 == uart_rx_pin) && (UART4_TX_P53 == uart_tx_pin))
|
||||
{
|
||||
P5M0 = 0x00;
|
||||
P5M1 = 0x01<<2;//P5.2 需要设置为高阻
|
||||
P_SW2 |= 0x04;
|
||||
}
|
||||
IE2 |= 0x01<<4; //允许串行口4中断
|
||||
busy[4] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 串口字节输出
|
||||
// @param uart_n 串口模块号(USART_1,USART_2,USART_3,USART_4)
|
||||
// @param dat 需要发送的字节
|
||||
// @return void
|
||||
// Sample usage: uart_putchar(UART_1,0xA5); // 串口1发送0xA5
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void uart_putchar(UARTN_enum uart_n,uint8 dat)
|
||||
{
|
||||
switch(uart_n)
|
||||
{
|
||||
case UART_1:
|
||||
while (busy[1]);
|
||||
busy[1] = 1;
|
||||
SBUF = dat;
|
||||
break;
|
||||
case UART_2:
|
||||
while (busy[2]);
|
||||
busy[2] = 1;
|
||||
S2BUF = dat;
|
||||
break;
|
||||
case UART_3:
|
||||
while (busy[3]);
|
||||
busy[3] = 1;
|
||||
S3BUF = dat;
|
||||
break;
|
||||
case UART_4:
|
||||
while (busy[4]);
|
||||
busy[4] = 1;
|
||||
S4BUF = dat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 串口发送数组
|
||||
// @param uart_n 串口模块号(USART_1,USART_2,USART_3,USART_4)
|
||||
// @param *buff 要发送的数组地址
|
||||
// @param len 发送长度
|
||||
// @return void
|
||||
// Sample usage: uart_putbuff(UART_1,&a[0],5);
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void uart_putbuff(UARTN_enum uart_n,uint8 *p,uint32 len)
|
||||
{
|
||||
while(len--)
|
||||
uart_putchar(uart_n,*p++);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
// @brief 串口发送字符串
|
||||
// @param uart_n 串口模块号(USART_1,USART_2,USART_3,USART_4)
|
||||
// @param *str 要发送的字符串地址
|
||||
// @return void
|
||||
// Sample usage: uart_putstr(UART_1,"i lvoe you");
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void uart_putstr(UARTN_enum uart_n,uint8 *str)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
uart_putchar(uart_n, *str++);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user