- 打卡等级:偶尔看看I
- 打卡总天数:15
- 最近打卡:2025-03-26 09:09:59
中级会员
- 积分
- 351
|
发表于 2024-8-27 16:26:29
|
显示全部楼层
/************* 本地变量声明 **************/
sbit SLEEP = P1^4;
sbit DECAY = P1^0;
//================== 步进电机相关变量定义 ===================
bit B_M1_RunEn; //运行允许
bit B_M1_RunEnTmp; //用于检测电机从运行到停止的事件
bit B_M1_DIR; //运行方向, 0:顺时针(正转), 1:逆时针(反转)
bit B_f1_update; //请求刷新频率值
bit B_TIMER1_12T; //定时器1时钟模式
u16 f1_period; //当前频率对应的周期
u16 f1; //当前频率
u16 f1_set; //目标频率
u16 f1_step; //加减速频率变化的步长
u16 M1_UpPulse; //加(减)速脉冲数
u16 M1_PulseCnt; //电机运行总脉冲数, 为0则连续运行
u16 M1_DownCnt; //运行到要减速输出的脉冲数
u8 M1_StepCnt; //步数计数
u8 M1_devide; //细分数 1, 2, 4, 8, 16, 32, 64
u8 M1_step; //步距, M1_step = 64 / M1_devide.
//===========================================================
//================== 串口相关变量定义 =======================
#define RX1_LENGTH 32
u8 RX1_Cnt; //接收字节计数
u8 RX1_TimerOut; //接收超时计数
u8 xdata RX1_Buffer[RX1_LENGTH]; //接收缓冲
bit B_RX1_OK; //接收到一块数据
bit B_TX1_Busy; //发送忙标志
//===========================================================
bit B_1ms; //1ms时隙标志
/************* 本地函数声明 **************/
//void PWMB_config(void);
void PWMA_config(void);
u8 Timer1_Config(u8 t, u32 reload); //t=0: reload值是主时钟周期数, t=1: reload值是时间(单位us)
u8 Timer0_Config(u8 t, u32 reload); //t=0: reload值是主时钟周期数, t=1: reload值是时间(单位us), 返回0正确, 返回1装载值过大错误.
void UART1_config(u32 brt, u8 timer, u8 io); // brt: 通信波特率, timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1, =1: 切换到P3.6 P3.7, =2: 切换到P1.6 P1.7, =3: 切换到P4.3 P4.4
void UART1_PrintString(u8 *puts);
void UART1_TxByte(u8 dat); // 串口1发送一个字节
void RX1_process(void); // 串口1处理函数
u16 GetStep(u16 f, u16 f_set); // 计算速度变化步进长度
void GetDownPulse(void); // 由M1_PulseCnt(总脉冲数) 和 M1_UpPulse(加速脉冲数) 计算开始减速的脉冲数, .
void LoadTimer1(void); // 计算更新频率的时间参数
void GetFreq1(void); // 计算加减速频率
void StopMotor1(void); // 停止运行一个电机
void RunMotor1(void); // 启动运行一个电机
void LockMotor1(void); //电机停止时减小电流锁转子
/******************** 主函数 **************************/
void main(void)
{
// PWMB_config(); //PWM初始化
P_SW2 |= 0x80; //扩展寄存器(XFR)访问使能
P1M1 = 0x00;
P1M0 = 0xff; //设置P1推挽输出
P3M1 = 0x2c; // 0 0 1 0 1 1 0 0
P3M0 = 0xd3; //设置P3推挽输出和高阻输入 1 1 0 1 0 0 1 1
DECAY = 0;
// nFAULT = 0;
SLEEP = 1;
PWMA_config();
Timer0_Config(0, MAIN_Fosc / 1000); //t=0: reload值是主时钟周期数, t=1: reload值是时间(单位us)
Timer1_Config(1, 20000); //t=0: reload值是主时钟周期数, t=1: reload值是时间(单位us, 这里随便给个值)
EA = 1;
B_M1_RunEn = 0;
B_M1_RunEnTmp = 0;
M1_StepCnt = 0;
M1_devide = 4; //细分数 1, 2, 4, 8, 16, 32, 64
M1_step = 64 / M1_devide; //倒数关系.
UART1_config(115200UL, 2, 0); // brt: 通信波特率, timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1, =1: 切换到P3.6 P3.7, =2: 切换到P1.6 P1.7, =3: 切换到P4.3 P4.4
UART1_PrintString("2相步进电机细分驱动程序\r\n");
UART1_PrintString("L1,500,1000 --> 马达1以500Hz正转1000个脉冲\r\n");
UART1_PrintString("R1,500,1000 --> 马达1以500Hz反转1000个脉冲\r\n");
UART1_PrintString("s --> 停止所有电机\r\n");
while (1)
{
if(B_1ms) //1ms时隙
{
B_1ms = 0;
if(B_M1_RunEn) //加减速处理
{
GetFreq1();
if(f1 < 100) B_M1_RunEn = 0; //停止
}
F0 = B_M1_RunEnTmp;
B_M1_RunEnTmp = B_M1_RunEn;
if(F0 && !B_M1_RunEnTmp) LockMotor1(); //检测到电机停止, 则锁转子, 减小电流
if(B_RX1_OK) //串口收到数据块
{
RX1_process(); //串口数据处理
B_RX1_OK = 0;
RX1_Cnt = 0;
}
}
}
}
/**********************************************/
#define UpTime 100 //加(减)速时间(ms)
u16 GetStep(u16 f, u16 f_set) //计算速度变化步进长度
{
u16 i;
M1_UpPulse = (u16)((u32)(f + f_set)*UpTime / 2000); // 理论加速脉冲数
if(f_set >= f) f_set = f_set - f; //计算频率差
else f_set = f - f_set; //计算频率差
i = f_set / UpTime; // 加(减)速步进
if(i == 0) i = 1; //步进不能为0
return i; //返回加减速步进值
}
void GetDownPulse(void) // 由M1_PulseCnt(总脉冲数) 和 M1_UpPulse(加速脉冲数) 计算开始减速的脉冲数, .
{
u16 pulse;
if(M1_PulseCnt != 0) //运行总脉冲数非0才有开始减速脉冲数
{
pulse = M1_UpPulse * 2; //加减速脉冲数之和 = M1_UpPulse * 2
if(M1_PulseCnt >= pulse) pulse = M1_UpPulse; //脉冲数 >= 加减速脉冲数之和, 则减速脉冲数按理论计算值
else pulse = M1_PulseCnt / 2; //脉冲数 < 加减速脉冲数之和, 则平分脉冲
M1_DownCnt = M1_PulseCnt - pulse; // 电机开始减速需要走过的脉冲数;
}
}
void LoadTimer1(void) //计算更新频率的时间参数
{
if(f1 < 100) f1 = 90;
if(f1 < 800) //频率太低用12T模式
{
B_TIMER1_12T = 1;
f1_period = 65536UL - MAIN_Fosc/12/f1;
}
else
{
B_TIMER1_12T = 0;
f1_period = 65536UL - MAIN_Fosc/f1;
}
B_f1_update = 1; //请求刷新
}
/************************************/
void GetFreq1(void) // 计算加减速频率
{
if(f1 < f1_set) //加速
{
f1 += f1_step;
if(f1 > f1_set) f1 = f1_set; //目标频率已到
LoadTimer1();
}
else if(f1 > f1_set) //减速
{
if(f1 < f1_step) f1 = 0;
else f1 -= f1_step;
if(f1 < f1_set) f1 = f1_set; //目标频率已到
LoadTimer1();
}
}
void StopMotor1(void) //停止运行一个电机
{
f1_set = 90; //小于100Hz则停止
f1_step = GetStep(f1, f1_set);
}
void RunMotor1(void) //启动运行一个电机
{
if(!TR1 || !B_M1_RunEn)
{
B_M1_RunEn = 1;
TR1 = 0;
LoadTimer1();
TL1 = (u8)(f1_period % 256);
TH1 = (u8)(f1_period / 256);
TR1 = 1;
}
}
/**********************************************/
void RX1_process(void) //串口1处理函数
{
u8 i;
u16 f, p;
if(RX1_Cnt == 1)
{
i = RX1_Buffer[0];
if((i == 's') || (i == 'S')) //大小写均停止
{
StopMotor1(); //"s" --> 停止所有电机
UART1_TxByte(i); //返回一个提示
}
}
if((RX1_Buffer[2] == ',') && (RX1_Cnt >= 5)) //有参数
{
for(f=0,i=3; i<RX1_Cnt; i++) //取频率 "L1,500,1000" --> 马达1以500Hz正转1000个脉冲
{ // "R1,500,1000" --> 马达1以500Hz反转1000个脉冲
if(RX1_Buffer[i] == ',') break; //碰到逗号结束
f = f * 10 + RX1_Buffer[i] - '0';
}
if(RX1_Buffer[i] != ',') f = 0; //数据异常
i++;
for(p=0; i<RX1_Cnt; i++) //取脉冲数
{
p = p * 10 + RX1_Buffer[i] - '0';
}
if(f >= 100) //有频率
{
if(RX1_Buffer[1] == '1') //电机1
{
M1_PulseCnt = p; //电机运行脉冲数, 如果为0, 则连续转动
f1_set = f; //目标频率
if(!B_M1_RunEn) f1 = 200; //电机未启动则从200HZ开始启动
f1_step = GetStep(f1, f1_set); //计算步进, 这个要先计算.
GetDownPulse(); //计算开始减速的脉冲数, 这个要后计算.
if(RX1_Buffer[0] == 'L') //顺时针
{
B_M1_DIR = 0;
RunMotor1(); //电机转向, 启动电机
UART1_TxByte('L'); //返回一个提示
}
if(RX1_Buffer[0] == 'R') //逆时针
{
B_M1_DIR = 1;
RunMotor1(); //电机转向, 启动电机
UART1_TxByte('R'); //返回一个提示
}
}
}
}
}
//========================================================================
// 函数: u8 Timer1_Config(u8 t, u32 reload)
// 描述: timer1初始化函数.
// 参数: t: 重装值类型, 0表示重装的是系统时钟数, 其余值表示重装的是时间(us).
// reload: 重装值.
// 返回: 0: 初始化正确, 1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-3-5
//========================================================================
u8 Timer1_Config(u8 t, u32 reload) //t=0: reload值是主时钟周期数, t=1: reload值是时间(单位us)
{
TR1 = 0; //停止计数
if(t != 0) reload = (u32)(((float)MAIN_Fosc * (float)reload)/1000000UL); //重装的是时间(us), 计算所需要的系统时钟数.
if(reload >= (65536UL * 12)) return 1; //值过大, 返回错误
if(reload < 65536UL) AUXR |= 0x40; //1T mode
else
{
AUXR &= ~0x40; //12T mode
reload = reload / 12;
}
reload = 65536UL - reload;
TH1 = (u8)(reload >> 8);
TL1 = (u8)(reload);
ET1 = 1; //允许中断
PT1 = 1; //高优先级中断
TMOD = (TMOD & ~0x30) | (0 << 4); //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装
TR1 = 1; //开始运行
return 0;
}
//========================================================================
// 函数: void timer1_ISR (void) interrupt TIMER1_VECTOR
// 描述: timer1中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2016-5-12
//========================================================================
void timer1_ISR (void) interrupt TIMER1_VECTOR
{
u8 area; //区间0~3
u8 pwm_A; //A相spwm
u8 pwm_B; //B相spwm
if(B_M1_RunEn) //电机允许运转
{
pwm_A = M1_StepCnt * M1_step; // A相步数计数, M1_step为细分对应的步距
area = pwm_A / 64; // 区间0~3
pwm_B = pwm_A + 64; // B相步数计数
pwm_A = T_SIN[pwm_A]; // A相sPWM值
pwm_B = T_SIN[pwm_B]; // A相sPWM值
if(area == 0) //0区间
{
PWMB_CCR5L = pwm_A; // A+ = sin(A)
PWMB_CCR6L = 0; // A- = 0
PWMB_CCR7L = pwm_B; // B+ = cos(A) = sin(A+64)
PWMB_CCR8L = 0; // B- = 0
}
else if(area == 1) //1区间
{
PWMB_CCR5L = pwm_A; // A+ = sin(A)
PWMB_CCR6L = 0; // A- = 0
PWMB_CCR7L = 0; // B+ = 0
PWMB_CCR8L = pwm_B; // B- = cos(A) = sin(A+64)
}
else if(area == 2) //2区间
{
PWMB_CCR5L = 0; // A+ = sin(A)
PWMB_CCR6L = pwm_A; // A- = 0
PWMB_CCR7L = 0; // B+ = 0
PWMB_CCR8L = pwm_B; // B- = cos(A) = sin(A+64)
}
else //3区间
{
PWMB_CCR5L = 0; // A+ = sin(A)
PWMB_CCR6L = pwm_A; // A- = 0
PWMB_CCR7L = pwm_B; // B+ = cos(A) = sin(A+64)
PWMB_CCR8L = 0; // B- = 0
}
if(B_M1_DIR == 0) M1_StepCnt++; //正转, 下一步, M1_step为细分对应的步距
else M1_StepCnt--; //反转, 下一步, M1_step为细分对应的步距
if(M1_PulseCnt != 0) //总脉冲数非0减1
{
if(--M1_PulseCnt == 0) B_M1_RunEn = 0;
}
if(M1_DownCnt != 0) //减速时刻脉冲数减1
{
if(--M1_DownCnt == 0) f1_set = 200;
}
}
if(B_f1_update) //刷新频率数据
{
B_f1_update = 0;
TR1 = 0;
TL1 = (u8)(f1_period % 256);
TH1 = (u8)(f1_period / 256);
if(B_TIMER1_12T) AUXR &= ~0x40; //12T mode
else AUXR |= 0x40; //1T mode
TR1 = 1;
}
}
void LockMotor1(void) //电机停止时减小电流锁转子
{
u8 area; //区间0~3
u8 pwm_A; //A相spwm
u8 pwm_B; //B相spwm
pwm_A = M1_StepCnt * M1_step; // A相步数计数
area = pwm_A / 64; // 区间0~3
pwm_B = pwm_A + 64; // B相步数计数
pwm_A = T_SIN[pwm_A]/2; // A相sPWM值
pwm_B = T_SIN[pwm_B]/2; // A相sPWM值
if(area == 0) //0区间
{
PWMB_CCR5L = pwm_A; // A+ = sin(A)
PWMB_CCR6L = 0; // A- = 0
PWMB_CCR7L = pwm_B; // B+ = cos(A) = sin(A+64)
PWMB_CCR8L = 0; // B- = 0
}
else if(area == 1) //1区间
{
PWMB_CCR5L = pwm_A; // A+ = sin(A)
PWMB_CCR6L = 0; // A- = 0
PWMB_CCR7L = 0; // B+ = 0
PWMB_CCR8L = pwm_B; // B- = cos(A) = sin(A+64)
}
else if(area == 2) //2区间
{
PWMB_CCR5L = 0; // A+ = sin(A)
PWMB_CCR6L = pwm_A; // A- = 0
PWMB_CCR7L = 0; // B+ = 0
PWMB_CCR8L = pwm_B; // B- = cos(A) = sin(A+64)
}
else //3区间
{
PWMB_CCR5L = 0; // A+ = sin(A)
PWMB_CCR6L = pwm_A; // A- = 0
PWMB_CCR7L = pwm_B; // B+ = cos(A) = sin(A+64)
PWMB_CCR8L = 0; // B- = 0
}
}
//========================================================================
// 函数: void PWMB_config(void)
// 描述: PWMB配置函数。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2020-5-17
// 备注:
//========================================================================
/*void PWMB_config(void)
{
P_SW2 |= 0x80; //SFR enable
PWMB_PSCR = 3; // 预分频寄存器, 分频 Fck_cnt = Fck_psc/(PSCR[15:0}+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)), 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).
PWMB_DTR = 0; // 死区时间配置, n=0~127: DTR= n T, 0x80 ~(0x80+n), n=0~63: DTR=(64+n)*2T,
// 对PWMB没有意义 0xc0 ~(0xc0+n), n=0~31: DTR=(32+n)*8T, 0xE0 ~(0xE0+n), n=0~31: DTR=(32+n)*16T,
PWMB_ARR = 256; // 自动重装载寄存器, 控制PWM周期
PWMB_CCER1 = 0;
PWMB_CCER2 = 0;
PWMB_SR1 = 0;
PWMB_SR2 = 0;
PWMB_ENO = 0; // IO输出允许, bit6: ENO8P, bit4: ENO7P, bit2: ENO6P, bit0: ENO5P
PWMB_PS = 0;
PWMB_IER = 0;
PWMB_CCMR1 = 0x68; // 通道模式配置, PWM模式1, 预装载允许
PWMB_CCR5 = 128; // 比较值, 控制占空比(高电平时钟数)
PWMB_CCER1 |= 0x01; // 开启比较输出, 高电平有效
PWMB_PS |= 0; // 选择IO, 0:选择P2.0, 1:选择P1.7, 2:选择P0.0, 3:选择P7.4,
PWMB_ENO |= 0x01; // IO输出允许, bit6: ENO8P, bit4: ENO7P, bit2: ENO6P, bit0: ENO5P
// PWMB_IER |= 0x02; // 使能中断
PWMB_CCMR2 = 0x68; // 通道模式配置, PWM模式1, 预装载允许
PWMB_CCR6 = 0; // 比较值, 控制占空比(高电平时钟数)
PWMB_CCER1 |= 0x10; // 开启比较输出, 高电平有效
PWMB_PS |= (0<<2); // 0:选择P2.1, 1:选择P5.4, 2:选择P0.1, 3:选择P7.5,
PWMB_ENO |= 0x04; // IO输出允许, bit6: ENO8P, bit4: ENO7P, bit2: ENO6P, bit0: ENO5P
// PWMB_IER |= 0x04; // 使能中断
PWMB_CCMR3 = 0x68; // 通道模式配置, PWM模式1, 预装载允许
PWMB_CCR7 = 0; // 比较值, 控制占空比(高电平时钟数)
PWMB_CCER2 |= 0x01; // 开启比较输出, 高电平有效
PWMB_PS |= (0<<4); // 选择IO, 0:选择P2.2, 1:选择P3.3, 2:选择P0.2, 3:选择P7.6,
PWMB_ENO |= 0x10; // IO输出允许, bit6: ENO8P, bit4: ENO7P, bit2: ENO6P, bit0: ENO5P
// PWMB_IER |= 0x08; // 使能中断
PWMB_CCMR4 = 0x68; // 通道模式配置, PWM模式1, 预装载允许
PWMB_CCR8 = 0; // 比较值, 控制占空比(高电平时钟数)
PWMB_CCER2 |= 0x10; // 开启比较输出, 高电平有效
PWMB_PS |= (0<<6); // 选择IO, 0:选择P2.3, 1:选择P3.4, 2:选择P0.3, 3:选择P7.7,
PWMB_ENO |= 0x40; // IO输出允许, bit6: ENO8P, bit4: ENO7P, bit2: ENO6P, bit0: ENO5P
// PWMB_IER |= 0x10; // 使能中断
PWMB_EGR = 0x01; //产生一次更新事件, 清除计数器和预分频计数器, 装载预分频寄存器的值
PWMB_BKR = 0x80; // 主输出使能 相当于总开关
PWMB_CR1 = 0x81; // 使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数, bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)
}
// PWMB_PS = (0<<6)+(0<<4)+(0<<2)+0; //选择IO, 4项从高到低(从左到右)对应PWM8 PWM7 PWM6 PWM5
// PWMB_PS PWM8 PWM7 PWM6 PWM5
// 00 P2.3 P2.2 P2.1 P2.0
// 01 P3.4 P3.3 P5.4 P1.7
// 02 P0.3 P0.2 P0.1 P0.0
// 03 P7.7 P7.6 P7.5 P7.4
*/
void PWMA_config(void)
{
P_SW2 |= 0x80; //SFR enable
PWMA_PSCR = 0x0000; // 预分频寄存器, 分频 Fck_cnt = Fck_psc/(PSCR[15:0}+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)), 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).
PWMA_DTR = 24; // 死区时间配置, n=0~127: DTR= n T, 0x80 ~(0x80+n), n=0~63: DTR=(64+n)*2T,
// 0xc0 ~(0xc0+n), n=0~31: DTR=(32+n)*8T, 0xE0 ~(0xE0+n), n=0~31: DTR=(32+n)*16T,
PWMA_ARR = 2400; // 自动重装载寄存器, 控制PWM周期
PWMA_CCER1 = 0;
PWMA_CCER2 = 0;
PWMA_SR1 = 0;
PWMA_SR2 = 0;
PWMA_ENO = 0;
PWMA_PS = 0;
PWMA_IER = 0;
// PWMA_ISR_En = 0;
PWMA_CCMR1 = 0x68; // 通道模式配置, PWM模式1, 预装载允许
PWMA_CCR1 = 400; // 比较值, 控制占空比(高电平时钟数)
PWMA_CCER1 |= 0x05; // 开启比较输出, 高电平有效
PWMA_PS |= 0; // 选择IO, 0:选择P1.0 P1.1, 1:选择P2.0 P2.1, 2:选择P6.0 P6.1,
PWMA_ENO |= 0x02; // IO输出允许, bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P, bit3: ENO2N, bit2: ENO2P, bit1: ENO1N, bit0: ENO1P
// PWMA_IER |= 0x02; // 使能中断
PWMA_CCMR2 = 0x68; // 通道模式配置, PWM模式1, 预装载允许
PWMA_CCR2 = 800; // 比较值, 控制占空比(高电平时钟数)
PWMA_CCER1 |= 0x50; // 开启比较输出, 高电平有效
PWMA_PS |= (0<<2); // 选择IO, 0:选择P1.2 P1.3, 1:选择P2.2 P2.3, 2:选择P6.2 P6.3,
PWMA_ENO |= 0x08; // IO输出允许, bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P, bit3: ENO2N, bit2: ENO2P, bit1: ENO1N, bit0: ENO1P
// PWMA_IER |= 0x04; // 使能中断
PWMA_CCMR3 = 0x68; // 通道模式配置, PWM模式1, 预装载允许
PWMA_CCR3 = 1200; // 比较值, 控制占空比(高电平时钟数)
PWMA_CCER2 |= 0x05; // 开启比较输出, 高电平有效
PWMA_PS |= (0<<4); // 选择IO, 0:选择P1.4 P1.5, 1:选择P2.4 P2.5, 2:选择P6.4 P6.5,
PWMA_ENO |= 0x20; // IO输出允许, bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P, bit3: ENO2N, bit2: ENO2P, bit1: ENO1N, bit0: ENO1P
// PWMA_IER |= 0x08; // 使能中断
PWMA_CCMR4 = 0x68; // 通道模式配置, PWM模式1, 预装载允许
PWMA_CCR4 = 1600; // 比较值, 控制占空比(高电平时钟数)
PWMA_CCER2 |= 0x50; // 开启比较输出, 高电平有效
PWMA_PS |= (3<<6); // 选择IO, 0:选择P1.6 P1.7, 1:选择P2.6 P2.7, 2:选择P6.6 P6.7, 3:选择P3.3 P3.4
PWMA_ENO |= 0x80; // IO输出允许, bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P, bit3: ENO2N, bit2: ENO2P, bit1: ENO1N, bit0: ENO1P
// PWMA_IER |= 0x10; // 使能中断
PWMA_BKR = 0x80; // 主输出使能 相当于总开关
PWMA_CR1 = 0x81; // 使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数, bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)
PWMA_EGR = 0x01; //产生一次更新事件, 清除计数器和预分频计数器, 装载预分频寄存器的值
// PWMA_ISR_En = PWMA_IER; //设置标志允许通道1~4中断处理
}
// PWMA_PS = (0<<6)+(0<<4)+(0<<2)+0; //选择IO, 4项从高到低(从左到右)对应PWM1 PWM2 PWM3 PWM4, 0:选择P1.x, 1:选择P2.x, 2:选择P6.x,
// PWMA_PS PWM4N PWM4P PWM3N PWM3P PWM2N PWM2P PWM1N PWM1P
// 00 P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
// 01 P2.7 P2.6 P2.5 P2.4 P2.3 P2.2 P2.1 P2.0
// 02 P6.7 P6.6 P6.5 P6.4 P6.3 P6.2 P6.1 P6.0
// 03 P3.3 P3.4 -- -- -- -- -- --
//========================================================================
// 函数:u8 Timer0_Config(u8 t, u32 reload)
// 描述: timer0初始化函数.
// 参数: t: 重装值类型, 0表示重装的是系统时钟数, 其余值表示重装的是时间(us).
// reload: 重装值.
// 返回: 0: 初始化正确, 1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-12-20
//========================================================================
u8 Timer0_Config(u8 t, u32 reload) //t=0: reload值是主时钟周期数, t=1: reload值是时间(单位us)
{
TR0 = 0; //停止计数
if(t != 0) reload = (u32)(((float)MAIN_Fosc * (float)reload)/1000000UL); //重装的是时间(us), 计算所需要的系统时钟数.
if(reload >= (65536UL * 12)) return 1; //值过大, 返回错误
if(reload < 65536UL) AUXR |= 0x80; //1T mode
else
{
AUXR &= ~0x80; //12T mode
reload = reload / 12;
}
reload = 65536UL - reload;
TH0 = (u8)(reload >> 8);
TL0 = (u8)(reload);
ET0 = 1; //允许中断
TMOD = (TMOD & ~0x03) | 0; //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
TR0 = 1; //开始运行
return 0;
}
//========================================================================
// 函数: void timer0_ISR(void) interrupt TIMER0_VECTOR
// 描述: timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2018-12-20
//========================================================================
void timer0_ISR(void) interrupt TIMER0_VECTOR
{
B_1ms = 1; //标志1ms时隙
if(RX1_TimerOut != 0) //串口接收超时处理
{
if(--RX1_TimerOut == 0)
{
if(RX1_Cnt != 0) B_RX1_OK = 1; //接收到一块数据
}
}
}
//========================================================================
// 函数: SetTimer2Baudraye(u16 dat)
// 描述: 设置Timer2做波特率发生器。
// 参数: dat: Timer2的重装值.
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 备注:
//========================================================================
void SetTimer2Baudraye(u16 dat) // 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
{
AUXR &= ~(1<<4); //Timer stop
AUXR &= ~(1<<3); //Timer2 set As Timer
AUXR |= (1<<2); //Timer2 set as 1T mode
TH2 = (u8)(dat >> 8);
TL2 = (u8)dat;
IE2 &= ~(1<<2); //禁止中断
AUXR |= (1<<4); //Timer run enable
}
//========================================================================
// 函数: void UART1_config(u32 brt, u8 timer, u8 io)
// 描述: UART1初始化函数。
// 参数: brt: 通信波特率.
// timer: 波特率使用的定时器, timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率.
// io: 串口1切换到的IO, io=1: 串口1切换到P3.0 P3.1, =1: 切换到P3.6 P3.7, =2: 切换到P1.6 P1.7, =3: 切换到P4.3 P4.4
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 备注:
//========================================================================
void UART1_config(u32 brt, u8 timer, u8 io) // brt: 通信波特率, timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1, =1: 切换到P3.6 P3.7, =3: 切换到P4.3 P4.4
{
brt = 65536UL - (MAIN_Fosc / 4) / brt;
if(timer == 2) //波特率使用定时器2
{
AUXR |= 0x01; //S1 BRT Use Timer2;
SetTimer2Baudraye((u16)brt);
}
else //波特率使用定时器1
{
TR1 = 0;
AUXR &= ~0x01; //S1 BRT Use Timer1;
AUXR |= (1<<6); //Timer1 set as 1T mode
TMOD &= ~(1<<6); //Timer1 set As Timer
TMOD &= ~0x30; //Timer1_16bitAutoReload;
TH1 = (u8)(brt >> 8);
TL1 = (u8)brt;
ET1 = 0; // 禁止Timer1中断
INT_CLKO &= ~0x02; // Timer1不输出高速时钟
TR1 = 1; // 运行Timer1
}
if(io == 1) {S1_USE_P36P37(); P3n_standard(0xc0);} //切换到 P3.6 P3.7
else if(io == 2) {S1_USE_P16P17(); P1n_standard(0xc0);} //切换到 P1.6 P1.7
else if(io == 3) {S1_USE_P43P44(); P4n_standard(0x18);} //切换到 P4.3 P4.4
else {S1_USE_P30P31(); P3n_standard(0x03);} //切换到 P3.0 P3.1
SCON = (SCON & 0x3f) | (1<<6); // 8位数据, 1位起始位, 1位停止位, 无校验
// PS = 1; //高优先级中断
ES = 1; //允许中断
REN = 1; //允许接收
}
//========================================================================
// 函数: void UART1_PrintString(u8 *puts)
// 描述: 串口1字符串打印函数
// 参数: puts: 字符串指针.
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 备注:
//========================================================================
void UART1_PrintString(u8 *puts)
{
for (; *puts != 0; puts++)
{
B_TX1_Busy = 1; //标志发送忙
SBUF = *puts; //发一个字节
while(B_TX1_Busy); //等待发送完成
}
}
void UART1_TxByte(u8 dat) //串口1发送一个字节
{
B_TX1_Busy = 1; //标志发送忙
SBUF = dat; //发一个字节
while(B_TX1_Busy); //等待发送完成
}
//========================================================================
// 函数: void UART1_ISR(void) interrupt UART1_VECTOR
// 描述: 串口1中断函数
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 备注:
//========================================================================
void UART1_ISR(void) interrupt UART1_VECTOR
{
if(RI)
{
RI = 0;
if(!B_RX1_OK)
{
if(RX1_Cnt >= RX1_LENGTH) RX1_Cnt = 0;
RX1_Buffer[RX1_Cnt++] = SBUF;
RX1_TimerOut = 5;
}
}
if(TI)
{
TI = 0;
B_TX1_Busy = 0;
}
}
|
|