车辆嵌入式实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验一串口通讯实验
一、实验目的
了解MC9SXS128单片机串行通讯模块、AD模块、PWM模块原理,并掌握使用。
二、实验内容
利用单片机自带的两个串行通讯口SCI0和SCI1,采集电位计电压值,SCI0串口查询发送AD采集值至SCI1,SCI1读取数据,通过PWM模块实现LED灯亮度无极调节。
三、实验原理图
四、实验源程序
#include <hidef.h>
#include <stdio.h>
#include "derivative.h"
#define BUS_CLOCK 32000000 //总线频率
#define OSC_CLOCK 16000000 //晶振频率
#define BAUD 9600 //波特率
//主控板上LED灯
#define LEDCPU PORTK_PK4
#define LEDCPU_dir DDRK_DDRK4
#define LED_ON 0
#define LED_OFF 1
unsigned char AD;
unsigned char data_receive;
unsigned int a=0;//串口接收指示灯
//函数初始化
void INIT_AD(void);
unsigned char AD_capture(void);
void INIT_PLL(void);//初始化锁相环
void init_pwm(void) ;//初始化PWM
void INIT_SCI(void); //初始化串口
void SCI0_send(unsigned char data);//串口发送程序
unsigned char SCI1_receive(void);//串口接收函数
//串口中断接收函数
#pragma CODE_SEG __NEAR_SEG NON_BANKED //中断函数置于非分页区内
void interrupt 21 receivedata(void)
{
a++;
data_receive= SCI1_receive();
PWMDTY0=data_receive;
if(a==1000)
{
a=0;
LEDCPU=~LEDCPU;
}
}
#pragma CODE_SEG DEFAULT //后续代码置于默认区域内
void main(void)
{
LEDCPU_dir=1; //定义为输出
LEDCPU=LED_ON;
DisableInterrupts;
INIT_PLL();
INIT_AD();
init_pwm();
INIT_SCI();
EnableInterrupts;
while(1)
{
AD=AD_capture();
SCI0_send(AD);
}
}
unsigned char SCI1_receive(void)
{
if(!SCI1SR1_RDRF); //等待发送数据寄存器满//接收数据寄存器空标志位return(SCI1DRL);
}
void INIT_SCI(void)
{
SCI0BD = BUS_CLOCK/16/BAUD; //设置SCI0波特率为9600
SCI0CR1 = 0x00; //设置SCI0为正常模式,八位数据位,无奇偶校验//10位数据异步传输,1位起始位,一位停止位,8位数据位
SCI0CR2 = 0x2c; //允许接收和发送数据,允许接收中断功能
SCI1BD = BUS_CLOCK/16/BAUD; //设置SCI1波特率为9600
SCI1CR1 = 0x00; //设置SCI1为正常模式,八位数据位,无奇偶校验//10位数据异步传输,1位起始位,一位停止位,8位数据位
SCI1CR2 = 0x2c; //允许接收和发送数据,允许接收中断功能
}
void INIT_PLL(void)
{
CLKSEL &= 0x7f; //set OSCCLK as sysclk
PLLCTL &= 0x8F; //Disable PLL circuit
CRGINT &= 0xDF;
SYNR = 0x43;
REFDV = 0x81; //PLLCLK=2×OSCCLK×(SYNR+1)/(REFDV+1)=64MHz ,fbus=32M
PLLCTL =PLLCTL|0x70; //Enable PLL circuit
asm NOP;
asm NOP;
while(!(CRGFLG&0x08)); //PLLCLK is Locked already
CLKSEL |= 0x80; //set PLLCLK as sysclk
}
void INIT_AD(void)
{
ATD0CTL2 = 0x40; //启动A/D模块,快速清零,禁止中断
ATD0CTL1_SRES=0; //选用8位模数转换
ATD0CTL3 = 0x88; //每次只转换一个通道
ATD0CTL4 = 0x07; //AD模块时钟频率为2MHz
}
unsigned char AD_capture(void)
{
unsigned char AD_data;
ATD0CTL5 = 0x08; //转换AD08
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
return(AD_data);
}
void init_pwm(void)
{
PWMPOL_PPOL0= 1; //通道的极性为高电平有效
PWMPRCLK = 0x22; //A时钟和B时钟的分频系数为4,频率为8MHz
PWMSCLA=0x04; //SA时钟频率为1MHz
PWMSCLB=0x04; //SB时钟频率为1MHz
PWMCLK = 0xFf; //0,1,2,3用SA时钟;4,5,6,7用SB时钟
PWMCAE = 0x00; //脉冲模式为左对齐模式
PWMPER0 = 255; //通道0的周期为3.9KHz
PWMDTY0 = 0; //通道0的占空比设置
PWME_PWME0=1; //使能PWM信号
}
void SCI0_send(unsigned char data)
{
while(!SCI0SR1_TDRE); //等待发送数据寄存器(缓冲器)为空//发送数据寄存器空标志位
SCI0DRL = data;
}
五、实验流程图
开始
初始化io口关中断初始化PLL 初始化AD
初始化SCI
开中断
采集AD08口
AD值
SCI0发送采集
值
读取SCI1数据
占空比赋值
初始化PWM
进SCI1中断
a++
a=0
Led灯亮灭变
化
a==1000?
退出SCI1中
断,返回主程
序
是
否
六、实验总结
串口SCI0查询发送方式为死循环方式,未调节发送间隔时间,如果采用硬件PIT定时中断发送或软件延时发送,则可调节发送间隔时间,效果更佳。
实验二液晶画点显示电压波形实验
一、实验目的
了解并掌握12864液晶屏、OLED屏显示原理,及MC9SXS128 PIT模块、AD 模块使用及中断编写方式。
二、实验内容
通过AD模块采集电位计电压值,实现12864液晶及OLED屏显示电压波形曲线。
三、实验原理图
四、实验源程序
1、12864液晶屏关键程序
unsigned char gdram[32][32];
unsigned char dianzhen[128];
//请空GDRAM
void clear_gdram(void)
{
unsigned char x,y;
for(y=0;y<32;y++)
{
for(x=0;x<32;x++)
{
gdram[x][y]=0x00;
}
}
}
//设置为绘图模式
void graph(void)
{
write_command(0x36);
delay20us(4);
}
//画点,刷新gdram[]
void draw_point(unsigned char x,unsigned char y)
{
unsigned intvx,vy,by,temp;
if(x>127||y>63)
return;
vy=x/8;
by=x%8;
if(y<=31)
{
vx=31-y;
vy=vy+16;
}
else
{
vx=63-y;
}
temp=1<<(7-by);
gdram[vx][vy]|=temp;
}
//更新GDRAM内容
void lcd_refresh(void)
{
unsigned char x,y;
for(y=0;y<32;y++)
{
for(x=0;x<16;x++)
{
write_command(0x34);//关闭绘图模式
write_command(y+0x80); //行地址
write_command(x+0x80); //列地址
write_command(0x30);
write_Data(gdram[y][2*x]);
write_Data(gdram[y][2*x+1]);
}
}
}
//中断程序
#pragma CODE_SEG __NEAR_SEG NON_BANKED void interrupt 66 pit0(void)
{
if(PITTF_PTF0 == 1)
PITTF_PTF0 = 1; //清除标志位
ad=AD_capture();
y=ad/4;
if(x<128)
{
draw_point(x,y);
dianzhen[x]=y;
x++;
}
else
{
clear_gdram();
for(i=0;i<127;i++)
{
dianzhen[i]=dianzhen[i+1];
draw_point(i,dianzhen[i]);
}
dianzhen[127]=y;
draw_point(127,y);
}
lcd_refresh();
graph();
LEDCPU=~LEDCPU;
}
#pragma CODE_SEG DEFAULT
2、OLED屏关键程序
unsigned char gram[128][8];
//更新GRAM内容
void Refresh_Gram(void)
{
unsigned char i,n;
for(i=0;i<8;i++)
{
OLED_WrCmd(0xb0+i);
OLED_WrCmd(0x00);
OLED_WrCmd(0x10);
for(n=0;n<128;n++)
{
OLED_WrDat(gram[n][i]);
}
}
}
//画点,刷新gram[]
void Draw_Point(unsigned char x,unsigned char y)
{
unsigned char pos,bx,temp=0;
if(x>127||y>63)
return;
pos=7-y/8;
bx=y%8;
temp=1<<(7-bx);
gram[x][pos]|=temp;
}
//清空GRAM
void Clear(void)
{
unsigned char i,n;
for(i=0;i<8;i++)
for(n=0;n<128;n++)
gram[n][i]=0X00;
Refresh_Gram();
}
//中断程序
#pragma CODE_SEG __NEAR_SEG NON_BANKED void interrupt 66 pit0(void)
{
if(PITTF_PTF0 == 1)
PITTF_PTF0 = 1; //清除标志位
ad=AD_capture();
y=ad/4;
if(x<128)
{
Draw_Point(x,y);
x++;
}
else
{
for(j=0;j<8;j++)
{
for(i=0;i<127;i++)
{
gram[i][j]=gram[i+1][j]; }
for(i=0;i<8;i++)
gram[127][i]=0x00; Draw_Point(127,y); } }
Refresh_Gram(); }
#pragma CODE_SEG DEFAULT
五、实验流程图
1、12864液晶屏程序流程图
开始
关中断PLL,PIT,AD,ECT ,GPIO 初始化
Led 灯亮清空GRAM 12864清屏
开图形显示
死循环
开中断
采集AD08通道
值y=ad/4
进PIT0中断
清PIT 标志位
更新gdram[](画点
(x,y))
更新数组dianzhen[]
x<128?
退出PIT0中断,返回主程
序
是
否
x++
清空GDRAM
数组dianzhen[]左移,dianzhen[127]不变
将gdram[]写入
GDRAM
led 灯亮灭取反
Dianzhen[127]
=y
开图形显示
更新gdram[](画点
(x,y))
2、OLED 屏程序流程图
开始
关中断
PLL,PIT,AD,ECT ,OLED 初始化
开中断
死循环
采集AD08通道
值
y=ad/4
进PIT0中断
清PIT 标志位
更新gram[]数组(画点(x,y))
x<128?
退出PIT0中断,返回主程
序
是
否
x++
OLED 画点(x,y)
数组gram[]左移,gram[127]不变
将gram[]写入
GRAM
更新gram[](画点(127,y))
六、实验效果
1、12864液晶屏实验效果
2、OLED屏实验效果
七、实验总结
12864液晶屏在画图模式中,更改GDRAM数据时,需要关闭画图模式而关闭12864液晶屏显示,在完成数据更改后再次显示,因屏幕自身性能限制,关闭显示和再次开启过程的时间较长,所以ad采样率较低,曲线的连续性较差;而OLED 屏则克服了这一缺陷,采样率在较高情况下也可完整显示,曲线的连续性较好。
实验三闭环控制节气门开度实验
一、实验目的
了解并掌握增量式PID算法,MC9SXS128 AD模块、PWM模块、PIT模块原理及使用。
二、实验内容
采集转把AD值和节气门AD值,通过增量式PID算法,输出PWM方波驱动节气门直流电机,调节节气门转动角度,使其随转把转动角度变化而变化。
三、实验原理图
四、实验源程序
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include "OLED.h"
#define BUS_CLOCK 32000000 //总线频率
#define OSC_CLOCK 16000000 //晶振频率
unsigned char ad,ad04;
intchazhi_old,chazhi=0;
intsum,inc=0;
float kp=0.025;
float ki=0.00002;
int out=0;
void INIT_AD(void)
{
ATD0CTL2 = 0x40; //启动A/D模块,快速清零,禁止中断
ATD0CTL1_SRES=0; //选用8位模数转换
ATD0CTL3 = 0x88; //每次只转换一个通道
ATD0CTL4 = 0x07; //AD模块时钟频率为2MHz
}
unsigned char AD_capture(void)
{
unsigned char AD_data;
ATD0CTL5 = 0x03; //转换AD03
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
return(AD_data);
}
unsigned char AD_capture_04(void)//摇杆
{
unsigned char AD_data;
ATD0CTL5 = 0x04; //转换AD04
while(!ATD0STAT0_SCF);
AD_data = ATD0DR0L;
return(AD_data);
}
void init_PIT(void)
{
PITMTLD0=255; //为0通道8位计数器赋值
PITLD0=400; //为0通道16位计数器赋值//(31+1)*(99+1)=16000000个总线周期=100us
PITMUX_PMUX0=0; //第0通道使用微计数器0
PITCE_PCE0=1; //第0通道计数器工作
PITCFLMT=0X80; //使能周期中断定时器
PITINTE_PINTE0=1; //0通道定时器定时中断被使能
}
void INIT_PLL(void)
{
CLKSEL &= 0x7f; //set OSCCLK as sysclk
PLLCTL &= 0x8F; //Disable PLL circuit
CRGINT &= 0xDF;
SYNR = 0x43;
REFDV = 0x81; //PLLCLK=2×OSCCLK×(SYNDIV+1)/(REFDIV+1)=64MHz ,fbus=32M
PLLCTL =PLLCTL|0x70; //Enable PLL circuit
asm NOP;
asm NOP;
while(!(CRGFLG&0x08)); //PLLCLK is Locked already
CLKSEL |= 0x80; //set PLLCLK as sysclk
}
void init_pwm(void)
{
PWMPOL_PPOL0= 1; //通道的极性为高电平有效
PWMPOL_PPOL1= 1; //通道的极性为高电平有效
PWMPRCLK = 0x22; //A时钟和B时钟的分频系数为4,频率为8MHz
PWMSCLA=0x04; //SA时钟频率为1MHz
PWMSCLA=0x04; //SB时钟频率为1MHz
PWMCLK = 0x03; //0和1用SA时钟
PWMCAE = 0x00; //脉冲模式为左对齐模式
PWMPER0 = 255; //通道0的周期为10KHz
PWMPER1 = 255; //通道1的周期为10KHz
PWMDTY0 = 0; //通道0的占空比设置
PWMDTY1 = 0; //通道1的占空比设置
PWME_PWME0=1;
PWME_PWME1=1;
}
#pragma CODE_SEG __NEAR_SEG NON_BANKED void interrupt 66 pit0(void)
{
if(PITTF_PTF0 == 1)
PITTF_PTF0 = 1; //清除标志位
ad04=AD_capture_04();
ad=AD_capture();
chazhi_old=chazhi;
chazhi=ad04-(255-ad);
sum=sum+chazhi;
out=out+(int)(kp*chazhi+ki*sum);
if(out>255)
out=255;
else if(out<0)
out=0;
PWMDTY01=out;
}
#pragma CODE_SEG DEFAULT
void main(void)
{
DisableInterrupts;
init_pwm();
INIT_PLL();
INIT_AD();
init_PIT();
OLED_Init();
EnableInterrupts;
for(;;)
{
}
}
五、实验流程图
开始关中断PLL,PIT,AD,PW M初始化
开中断
死循环
采集
ad_04=AD04、
ad=AD03通道
值chazhi_old=cha
zhi 进PIT0中断
清PIT 标志位out=255
out>255?退出PIT0中断,返回主程
序
是否
out=out+(int)(k p*chazhi+ki*su
m)
chazhi=ad04-
(255-ad)积分
sum=sum+chaz
hi;out=0
out<=0?PWMDTY01=
out
是否
六、实验总结
本次实验没有采用老师所给程序,而是采用增量式PI 控制,通过不断设置比例和积分参数以到达理想实验结果,虽然最终节气门转动角度稳定在理想位置,但是其在稳定前的超调量与稳定时间均比较大,系统的快速响应性不是很理想。
课程总结。