昨天简单的把代码写完了,其实也超简单,主要及部分步进电机控制、UART通信。
DEV层
dev层为硬件层,主要和单片机寄存器打交道,完成I/O口初始化,uart初始化。
初始化i/o口
默认51的准双向口,弱上拉驱动uln2803没问题。
void dev_init_pin(void)
{
P1M1=0;P1M0=0;
P2M1=0;P2M0=0;
P3M1=0;P3M0=0;
}
初始化uart
波特率:9600 数据位:8位 1停止位 无校验。而且串口开启中断接收发送,在main函数打开中断标志位。
void dev_init_uart(void)
{
SCON=0X50;
TMOD=0X20;
TH1=-3; //9600
TL1=-3;
ES=1;
EA=1;
TR1=1;
}
HAL层
hal层为硬件抽象层,主要负责模块实例化。负责板级初始化、步进电机控制、ir-cut自控、内部flash操作。
步进电机控制
步进电机转一圈360°,64步。hal_turn_up_motor向上转头函数,向下、左、右函数类似我就不贴出来了。param t为步数。左右转337.5°,分五个位置,每转一位置15步;上下3个位置,每转一位置4步。
sbit HAL_MOTOR_UD_F1 =P1^2;
sbit HAL_MOTOR_UD_F2 =P1^1;
sbit HAL_MOTOR_UD_F3 =P1^0;
sbit HAL_MOTOR_UD_F4 =P3^7;
sbit HAL_MOTOR_LR_F1 =P1^6;
sbit HAL_MOTOR_LR_F2 =P1^5;
sbit HAL_MOTOR_LR_F3 =P1^4;
sbit HAL_MOTOR_LR_F4 =P1^3;
void delay(unsigned int t)
{
unsigned int k;
while(t--)
{
for(k=0; k<125; k++)
{ }
}
}
void hal_turn_up_motor(unsigned int n)
{
unsigned char i;
unsigned int j;
for (j=0; j<8*n; j++){
for (i=0; i<8; i++){
switch(i){
case 0:HAL_MOTOR_UD_F1=1;HAL_MOTOR_UD_F2=0;HAL_MOTOR_UD_F3=0;HAL_MOTOR_UD_F4=0;
break;
case 1:HAL_MOTOR_UD_F1=1;HAL_MOTOR_UD_F2=1;HAL_MOTOR_UD_F3=0;HAL_MOTOR_UD_F4=0;
break;
case 2:HAL_MOTOR_UD_F1=0;HAL_MOTOR_UD_F2=1;HAL_MOTOR_UD_F3=0;HAL_MOTOR_UD_F4=0;
break;
case 3:HAL_MOTOR_UD_F1=0;HAL_MOTOR_UD_F2=1;HAL_MOTOR_UD_F3=1;HAL_MOTOR_UD_F4=0;
break;
case 4:HAL_MOTOR_UD_F1=0;HAL_MOTOR_UD_F2=0;HAL_MOTOR_UD_F3=1;HAL_MOTOR_UD_F4=0;
break;
case 5:HAL_MOTOR_UD_F1=0;HAL_MOTOR_UD_F2=0;HAL_MOTOR_UD_F3=1;HAL_MOTOR_UD_F4=1;
break;
case 6:HAL_MOTOR_UD_F1=0;HAL_MOTOR_UD_F2=0;HAL_MOTOR_UD_F3=0;HAL_MOTOR_UD_F4=1;
break;
case 7:HAL_MOTOR_UD_F1=1;HAL_MOTOR_UD_F2=0;HAL_MOTOR_UD_F3=0;HAL_MOTOR_UD_F4=1;
break;
default:
break;
}
delay(15);
}
}
}
flash操作
内部e2rom的操作直接用的官方的代码,自己用的时候封装一层就OK。
#define ADDR_ID 0x07F9
/*Declare SFR associated with the IAP */
sfr IAP_DATA = 0xC2; //Flash data register
sfr IAP_ADDRH = 0xC3; //Flash address HIGH
sfr IAP_ADDRL = 0xC4; //Flash address LOW
sfr IAP_CMD = 0xC5; //Flash command register
sfr IAP_TRIG = 0xC6; //Flash command trigger
sfr IAP_CONTR = 0xC7; //Flash control register
/*Define ISP/IAP/EEPROM command*/
#define CMD_IDLE 0 //Stand-By
#define CMD_READ 1 //Byte-Read
#define CMD_PROGRAM 2 //Byte-Program
#define CMD_ERASE 3 //Sector-Erase
/*Define ISP/IAP/EEPROM operation const for IAP_CONTR*/
//#define ENABLE_IAP 0x80 //if SYSCLK<30MHz
//#define ENABLE_IAP 0x81 //if SYSCLK<24MHz
#define ENABLE_IAP 0x82 //if SYSCLK<20MHz
//#define ENABLE_IAP 0x83 //if SYSCLK<12MHz
//#define ENABLE_IAP 0x84 //if SYSCLK<6MHz
//#define ENABLE_IAP 0x85 //if SYSCLK<3MHz
//#define ENABLE_IAP 0x86 //if SYSCLK<2MHz
//#define ENABLE_IAP 0x87 //if SYSCLK<1MHz
/*----------------------------
Disable ISP/IAP/EEPROM function
Make MCU in a safe state
----------------------------*/
void IapIdle()
{
IAP_CONTR = 0; //Close IAP function
IAP_CMD = 0; //Clear command to standby
IAP_TRIG = 0; //Clear trigger register
IAP_ADDRH = 0x80; //Data ptr point to non-EEPROM area
IAP_ADDRL = 0; //Clear IAP address to prevent misuse
}
/*----------------------------
Read one byte from ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
Output:Flash data
----------------------------*/
unsigned char IapReadByte(unsigned int addr)
{
unsigned char dat; //Data buffer
IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
IAP_CMD = CMD_READ; //Set ISP/IAP/EEPROM READ command
IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
IAP_TRIG = 0x5a; //Send trigger command1 (0x5a)
IAP_TRIG = 0xa5; //Send trigger command2 (0xa5)
_nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
dat = IAP_DATA; //Read ISP/IAP/EEPROM data
IapIdle(); //Close ISP/IAP/EEPROM function
return dat; //Return Flash data
}
/*----------------------------
Program one byte to ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
dat (ISP/IAP/EEPROM data)
Output:-
----------------------------*/
void IapProgramByte(unsigned int addr, unsigned char dat)
{
IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
IAP_CMD = CMD_PROGRAM; //Set ISP/IAP/EEPROM PROGRAM command
IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
IAP_DATA = dat; //Write ISP/IAP/EEPROM data
IAP_TRIG = 0x5a; //Send trigger command1 (0x5a)
IAP_TRIG = 0xa5; //Send trigger command2 (0xa5)
_nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
IapIdle();
}
APP层
app层负责最上层业务处理。简化一下就是发送 0x68和0x16控制电机上下转动指定角度。
char uuu =2;
void main()
{
app_init_machine();
ES = 1;
EA = 1;
while(1){
// app_task_loop();
if(uuu == 0){
hal_turn_up_motor(4);
uuu =2;
}else if(uuu == 1){
hal_turn_down_motor(4);
uuu =2;
}
}
}
void UART_ISR (void) interrupt 4 using 1
{
if(RI == 1){
RI = 0;
g_uart_data.RXData = SBUF;
if(g_uart_data.RXData == 0x68){
uuu =1;
}else if(g_uart_data.RXData == 0x16){
uuu =0;
}
}
}
基本代码和业务就是这样了,只要通过uart接口这套代码都可以用,主要看外挂的什么芯片了485呀、can呀、wifi模块······