Primary Engineering Practice

engerineering time

Finding

十多天了谢谢两条大腿带飞

每天都可以准时吃饭非常爽

hhhh虽然每天也是花式懵逼地坐在一边有点惭愧

(:з」∠)总之非常开心的(

—by rxy

很有意思的课程,怪不得那么多人怀念小学期.

disappear

实训最开始三天去参加4+2了,把两个队友抛在珠海焊电路板感觉还是有一些愧疚.4+2被淘汰那天看到电路板真是那天唯一的欣慰与感动.有点可惜错过了这份雕琢的经历.不过这张照片还是在那天朋友圈刷屏中特别醒目.

learn C

不过4+2回来后,对于位运算有莫名的信心.所以在回来前几天发现都是在水一些C语言的知识后..觉得实训怎么这么水啊…..每天都能早早的水完task然后就快乐的离场吃饭…

那两三天真的过得挺轻松的…每天讲一点大一最开始自学的C语言…然后就水几个task.

然后发现俊爷在快乐的刷进度0.0舍友对他也赞美有嘉233

不过真的水到好无聊..于是就开始大冒险…

有一次debugTASK看了两个后直接把文杰喊了过来验收..

然后水到倒数第二个时候发现..居然是一道写代码题.

然后文杰留下了一句评价

空手套白狼

FPGA

整个实训中最恐怖的传说便是烧掉一块FPGA板子了

因为淘宝价1200…简直精贵了整个实验的配置..

每一天都有烧板子的消息传来…没想到有一天终于轮到了我们组..

调试了一个下午后发现小车有毒…居然不能脱离USB线

把问题归罪到H桥后去找老师更换H桥…

过了十分钟队长还没回来..去看一眼得知板子坏了…

那个心情还是挺忐忑的..

那个TA顺便恐吓了我们一人200的要求= =

然后似乎那次验收顺便收货了一个B…

(字居然写的这么丑了-.-)

最后一天整整一个上午…都ELF过去..问文杰= =我们又被”恐吓”恭喜中奖了…

中午得知换了台电脑可以烧了..兴奋地不会宿舍洗澡睡觉直接滚去实验室干活了233

Teachers

移动的TA果然超级赞..发现他们不在电工群后就去私加了一个TA的QQ..想要问要不要带板子和小车来上课..结果那天TA8:50回了我一句不要= =/////

见识了文杰师兄的卖萌.简直有趣到可怕..居然把我的语气语调带的有点标普了..然而文杰似乎也是fu南的??!!每次都被莫名喊成”大腿”立得一手好flag..于是守候到了实验室关门的晚霞0.0可惜文杰居然不要我爆照..真的好萌XD

huangkai老师的慕尼黑工业大学的团队0….0据说高薪聘请过来的..似乎让我在雅礼的招生群装了一个逼…另外上课似乎觉得我们大一还是通识教育..鼓励我们创新精神?几次样例代码都有一些小bug..什么Switch大写了首字母..接口多了一个参数!!?….估计就是防止我们copy&paste的小tirck吧..

不过说实话..被坑(水)久了之后..还是觉得TA讲课会切中要害一些.

另外外教这种生物..在我出国梦暗淡之后…就成了我自习的一个借口了2333

else1

这几天每一天晚上都好悠闲啊2333..

终于享受到了一年级学生应有的愉悦

水完了一本\

不知道谁安利的书…

一章学一个引擎简直可怕..

然后美化博客debug很久..换了个域名2333

…于是每次我都是朋友圈错乱感的制造者

else2

这次实训两个室友都当上了他们组的大腿2333

每天回宿舍给我各种秀-.-

似乎看到他们下个学期冉冉升起的学霸希望

而且我们宿舍崛起的绩点23333

最后有一点想提的是..这几天伙食也是经历了由万象纷呈到过零丁洋再到普通中珠伙食的经历.给大家一点希望吧..中珠太美..但是暑假还是东校伙食美(每次逛食堂都能快乐地..抓一盘菜233)

面向硬件的编程主要是对于宏文件的套用

说白了,就是学会用模板.

很不幸的是苦于找模板.忘模板…这样就还是很尴尬.

–原文抬头

预备工作

  1. 加载C盘驱动)
  2. Quartus载入单片机,载入sof文件
  3. 打开eclipse,创建工程,载入NIOS_Sys.sopcinfo(也在上面那个链接中)
  4. eclipse编译的时候需要忽略两个选项.
  5. FPGA文档

头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//standard C library
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h> //like int16_t;
#include <stdbool.h>

//else
#include "io.h"
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include <altera_avalon_performance_counter.h>

//what?
#include "sys/alt_irq.h"
#include "adc_spi_read.h"
#include "terasic_includes.h"
#include "alt_types.h"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "terasic_includes.h"
/*
#include <stdio.h>
#include <stdlib.h> // malloc, free
#include <string.h>
#include <stddef.h>
#include <unistd.h> // usleep (unix standard?)
#include <io.h>
#include "sys/alt_flash.h"
#include "sys/alt_flash_types.h"
#include "alt_types.h" // alt_u32
#include "altera_avalon_pio_regs.h" //IOWR_ALTERA_AVALON_PIO_DATA
#include "sys/alt_irq.h" // interrupt
#include "sys/alt_alarm.h" // time tick function (alt_nticks(), alt_ticks_per_second())
#include "sys/alt_timestamp.h"
#include "sys/alt_stdio.h"
#include "system.h"
#include <fcntl.h>
#include "terasic_debug.h"
typedef int bool;
#define TRUE 1
#define FALSE 0
*/

1
2
3
4
5
6
7
8
9
10
11
#include "alt_types.h"
/*
typedef signed char alt_8;
typedef unsigned char alt_u8;
typedef signed short alt_16;
typedef unsigned short alt_u16;
typedef signed long alt_32;
typedef unsigned long alt_u32;
typedef long long alt_64;
typedef unsigned long long alt_u64;
*/

基本IO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//基本亮灯方式
IOWR(LED_BASE,0,0xff);

//机器key按压状态
KEY_BASE

// write register
IOWR(LED_BASE,0,led);

int value = 1;//按照输出数的二进制位亮灯
IOWR_ALTERA_AVALON_PIO_DATA( PIO_LED_BASE, value );

// read register, 普通情况下是3 if(val ^ 3)说明被按键,自动带有防抖
int value = IORD_ALTERA_AVALON_PIO_DATA( PIO_LED_BASE );

中断

中断就是在程序任意阶段突然发生的一个函数

清空中断标记之后还原.

 Initialization

Enable the interrupt for the specific input

IOWR_ALTERA_AVALON_PIO_IRQ_MASK(, );

 Set the edge capability

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(, )

 Register handler

alt_ic_isr_regsiter( , ,, , )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
volatile static char key = 0;

unsigned int nirq_isr_context;
void nIRQ_Initial(void);//记得在main中initial
void isr_function(void);//记得声明在前面...

void nIRQ_Initial(void)
{

//todo: set up interrupt function
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(KEY_BASE,3);//3 = 1 | 2,表示1和2输入时都有反应

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x1);//这句话是清空中断状态

alt_ic_isr_register( 0, 1,isr_function, 0, 0 );//声明中断函数

}
void isr_function(void)
{

//do something
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x1);
}

计时模块

usleep(264762)大概是一秒.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

//开始计时器
PERF_RESET(PERFORMANCE_COUNTER_BASE);
PERF_START_MEASURING(PERFORMANCE_COUNTER_BASE);
PERF_BEGIN(PERFORMANCE_COUNTER_BASE,1);//1在这里是个标示,标示1号位的计数 重复计数会累加,

/*
想要测试间的函数部分 ,每一个测试时间块设置一个函数出去,比如这里测的print函数

当然不写函数也是可以的,可以把下面的"printf"改成"for"便可以测试for循环的时间

所以我认为是在第一个BEGIN和END之间找到一个关键字(如果把下面的2改成1,它会记成上面的时间)
*/


PERF_END(PERFORMANCE_COUNTER_BASE,1);//结束时间计数,对应上面1的标志


PERF_BEGIN(PERFORMANCE_COUNTER_BASE,2);
//usleep(1000);//这个是一个sleep封装,下面的for循环暴力模拟
//for(i = 0;i < 200000 ;i++); 如果要测试usleep时间的话那么就得写在第2个 计时区域里面
PERF_END(PERFORMANCE_COUNTER_BASE,2);


//最后一个标志stop
PERF_STOP_MEASURING(PERFORMANCE_COUNTER_BASE);
//按照它的模板输出时间
perf_print_formatted_report(PERFORMANCE_COUNTER_BASE,alt_get_cpu_freq(),
2,"printf","usleep","IOWR");//第一个是输出时间的种类,后面的是要求测试的函数

//printf("Product of entered matrices: %d \n",*timer);

perf_get_total_time

1
2
3
4
5
6
alt_u64 perf_get_total_time   (void* hw_base_address)
{


return perf_get_section_time (hw_base_address, 0);

}

subTask Volatilevariables

这个实在eclipse里面把编译选项级别改高(level2)后,很多变量被”优化”到不能修改的尴尬地步.

subTask 存储位置

1
2
3
4
5
6
7
8
9
10
11
12
//不同存储位置声明 ,onclip是会快一些的.
#define USE_ONCHIP_MEMORY

#ifdef USE_ONCHIP_MEMORY
int first[10][10] __attribute__ (( section ( ".onchip_memory2_0" )));
int second[10][10] __attribute__ (( section ( ".onchip_memory2_0" )));
int multiply[10][10] __attribute__ (( section ( ".onchip_memory2_0" )));
#else
int first[10][10];
int second[10][10];
int multiply[10][10];
#endif

读入电压

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#define START_FLAG  0x8000 //标记已经测量
#define DONE_FLAG 0x8000


const int adc_channel = 2;//输入信号端口

volatile static char key = 0;//按键(中断)

int done = 0;//成功读取电压值
int spi_response; // 读取电压值


unsigned int nirq_isr_context;
void nIRQ_Initial(void);//记得在main中initial
void isr_function(void);//记得声明在前面...

void nIRQ_Initial(void)
{

//todo: set up interrupt function
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(KEY_BASE,3);//3 = 1 | 2,表示1和2输入时都有反应

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x1);//这句话是清空中断状态

alt_ic_isr_register( 0, 1,isr_function, 0, 0 );//声明中断函数

}
void isr_function(void)
{

//set the desired channel by writingit to the SPI bus.绑定?(terry)
IOWR(ADC_SPI_READ_BASE,0,adc_channel);//初始接口信号,必须每次中断初始化,取消START_FLAG
// start the converstion by writingthe START_FLAG to the SPI bus.(terry)
IOWR(ADC_SPI_READ_BASE,0,adc_channel | START_FLAG);//写入当前接口信号

done=0;//done去掉也可以实现任务.
while(!done)
{
//只有最高位为1才代表SPI从ADC读取完成。(terry)
spi_response = IORD(ADC_SPI_READ_BASE,0); //读出当前借口信号
done = (spi_response & DONE_FLAG); //如果读出成功
}

int adc_value = spi_response & 0xFFF; //取有效位电压值

printf("voltage = %d\n", adc_value);
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x1);
}




int main()
{

nIRQ_Initial();//中断初始化
while(1)
{
//中断触发,输出ADC值
}
printf("done = %d\n",done); //检查时DONE_FLAG
return 0;
}

SUBTASK 测量实际电压数值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//增设这个函数的目的是为了去噪.(平均值采样分析)
double test()
{

IOWR(ADC_SPI_READ_BASE,0,adc_channel);//初始接口信号
done=0;
IOWR(ADC_SPI_READ_BASE,0,adc_channel | START_FLAG);//写入当前接口信号
while(!done)
{
spi_response = IORD(ADC_SPI_READ_BASE,0); //读出当前借口信号
done = (spi_response & DONE_FLAG); //如果读出成功
}
int adc_value = spi_response & 0xFFF; //取有效位电压值

printf("voltage = %lfV\n", 3.3*adc_value/4096);
return 3.3*adc_value/4096;
}

来自terry博客对于信号处理的一段解释,我觉得很有意思

ADC 将模拟型号转换成数字信号,通常地,

假如传感器测量范围是 0V-3.3V,ADC 是 12bit

0V 时是 0000 0000 00003.3V 时是 1111 1111 1111

由于转换是线性的所以 voltage = adc_value * 3.3 / 4096。(2^12 = 4096)

这样之后mask也很好理解了

真正有意义的位是后面三个十六进制位(也就是后面12位01位)

那么mask = 0x8000 = 1000 0000 0000 0000 是首位掩码标记.

adc_channel | START_FLAG 其实就是一个绑定,但是加上了一个mask(正常电压范围达不到mask)

spi_response & DONE_FLAG是在探测mask位是否有值,也就是检查start_flag

spi_response & 0xFFF 取出来的时候需要提取有效部分,也就是后面12位.

举个例子(由于md样式|表示成or):

-变量名/表达式 -对应二进制数值
adc_channel = 2 0000 0000 0000 0010
adc_channel or START_FLAG 1000 0000 0000 0010
spi_response = 1000 0011 1111 1111 1000 0011 1111 1111
spi_response & DONE_FLAG 1000 0000 0000 0000
spi_response & 0xFFF 0000 0011 1111 1111
START_FLAGDONE_FLAG 1000 0000 0000 0000

PWM

PWM就是用数字信号的比率实现模拟信号的高低

硬件实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
* main.c
*
* Created on: 07.11.2012
* Author: karl_ee
*/


#include "main.h"

int main()
{

unsigned int i,j;
unsigned long phase1=0x0,phase2=0x000//分别是任务一和任务二的初始相位
,duty1=0x1388,duty2=0x1388//分别是任务一输出和任务二输出占空比
,period=0x186A//前面的相位和占空比需要与这个period作比
,enable=0x1;//0x3才能输出两个信号
while(1)
{
motor_setting(phase1,duty1,phase2,duty2,period,enable);
for(i=0;i<2550;i++)
for(j=0;j<2550;j++);//delay
}
}

/*
* motor_setting.c
*
* Created on: 07.11.2012
* Author: karl_ee
* input parameters:
* phase: range from 0 to value of period
* duty cycle: set to number=period*percentage of duty cycle
* period: according to the freq of cpu,
* normally the period should be set to the value
* that makes the freq of pwm waveform to be 15 k
* e.g., for 50MHz, value should be 3333(0xD05)
* enable:'0' represents off, '1' is on, lease significant bit is for channel 1
* e.g., for channel 1 on and channel 2 off, enable=0x1
*
*/


#include "motor_setting.h"

void motor_setting(unsigned long phase1, unsigned long duty1
,unsigned long phase2, unsigned long duty2
,unsigned long period,unsigned long enable)

{

unsigned long * pwm_en= (unsigned long *)PWM_EN;
unsigned long * pwm_period=(unsigned long *)PWM_PERIOD;
unsigned long * pwm_phase1=(unsigned long *)PWM_PHASE1;//这个是位置=>.h头文件
unsigned long * pwm_phase2=(unsigned long *)PWM_PHASE2;
unsigned long * pwm_duty1=(unsigned long *)PWM_DUTY1;
unsigned long * pwm_duty2=(unsigned long *)PWM_DUTY2;

* pwm_en=enable;
* pwm_period=period;
* pwm_phase1=phase1;
* pwm_phase2=phase2;
* pwm_duty1=duty1;
* pwm_duty2=duty2;

}


/*
* motor_setting.h
*
* Created on: 07.11.2012
* Author: karl_ee
* input parameters:
* phase: range from
* duty cycle:
* period: according to the freq of cpu,
* normally the period should be set to the value
* that makes the freq of pwm waveform to be 15 k
* e.x for 50MHz, value should be 3333(0xD05)
* enable:'0' represents off, '1' is on
*/


#ifndef MOTOR_SETTING_H_
#define MOTOR_SETTING_H_

#include "system.h"

#define PWM_EN PWM0_BASE
#define PWM_PERIOD PWM0_BASE+1
#define PWM_DUTY1 PWM0_BASE+2
#define PWM_DUTY2 PWM0_BASE+3
#define PWM_PHASE1 PWM0_BASE+4//
#define PWM_PHASE2 PWM0_BASE+5

void motor_setting(unsigned long phase1, unsigned long duty1,unsigned long phase2, unsigned long duty2,
unsigned long period,unsigned long enable)
;

#endif /* MOTOR_SETTING_H_ */

顺着线索一路找下去可以在NIOSCar.qsf里面找到这样一段

1
2
3
4
5
6
7
#-------------------------------------------------------------
#reuse above pins for PWM0-3
#-------------------------------------------------------------
set_location_assignment PIN_B6 -to PWM0Ch0
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to PWM0Ch0
set_location_assignment PIN_A6 -to PWM0Ch1
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to PWM0Ch1

也就是说它把BASE赋给B6A6位了,在DE0_Nano_User_Manual_v1.9.pdf里面大概12页找到对应管脚以及它上面的物理位置,然后就有输出信号了.

软件实现

1
2
3
4
5
6
7
8
unsigned int i;
for (i=1; i < 100; i++)
{
if (i<30)
IOWR(PIO0_BASE, 0, 0);//这里的宏定义参考ppt
else
IOWR(PIO0_BASE, 0, 1);
}

然后对应这一段

1
2
3
4
5
#============================================================
# GPIO_0, GPIO_0 connect to GPIO Default
#============================================================
set_location_assignment PIN_D3 -to GPIO_0[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO_0[0]

RUN THE CAR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
组合了一些函数在这里
能让小车run起来~~~
1. 有两个头文件有毒..这里删了
2. 把main.h 和 motor_setting.h 仿制了一份
3. 采用pwm2,也就是pwm0后面两位的接口.
*/


//standard C library
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h> //like int16_t;
#include <stdbool.h>

//else
#include "io.h"
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include <altera_avalon_performance_counter.h>

//what?
#include "sys/alt_irq.h"
#include "alt_types.h"

typedef signed char char_8;
typedef unsigned char uchar_8;
typedef signed short short_16;
typedef unsigned short ushort_16;
typedef signed long long_32;
typedef unsigned long ulong_32;
typedef long long long_64;
typedef unsigned long long ulong_64;

//first mortor
#define PWM_EN PWM0_BASE
#define PWM_PERIOD PWM0_BASE+1
#define PWM_DUTY1 PWM0_BASE+2
#define PWM_DUTY2 PWM0_BASE+3
#define PWM_PHASE1 PWM0_BASE+4
#define PWM_PHASE2 PWM0_BASE+5

void motor_setting(unsigned long phase1, unsigned long duty1,
unsigned long phase2, unsigned long duty2,
unsigned long period,unsigned long enable)

{

unsigned long * pwm_en= (unsigned long *)PWM_EN;
unsigned long * pwm_period=(unsigned long *)PWM_PERIOD;
unsigned long * pwm_phase1=(unsigned long *)PWM_PHASE1;
unsigned long * pwm_phase2=(unsigned long *)PWM_PHASE2;
unsigned long * pwm_duty1=(unsigned long *)PWM_DUTY1;
unsigned long * pwm_duty2=(unsigned long *)PWM_DUTY2;

* pwm_en=enable;
* pwm_period=period;
* pwm_phase1=phase1;
* pwm_phase2=phase2;
* pwm_duty1=duty1;
* pwm_duty2=duty2;
}
//仿造PWM0函数写下的PWM2宏定义以及函数
#define PWM_EN1 PWM2_BASE
#define PWM_PERIOD1 PWM2_BASE+1
#define PWM_DUTY11 PWM2_BASE+2
#define PWM_DUTY21 PWM2_BASE+3
#define PWM_PHASE11 PWM2_BASE+4
#define PWM_PHASE21 PWM2_BASE+5
void motor_setting1(unsigned long phase1, unsigned long duty1,
unsigned long phase2, unsigned long duty2,
unsigned long period,unsigned long enable)

{

unsigned long * pwm_en= (unsigned long *)PWM_EN1;
unsigned long * pwm_period=(unsigned long *)PWM_PERIOD1;
unsigned long * pwm_phase1=(unsigned long *)PWM_PHASE11;
unsigned long * pwm_phase2=(unsigned long *)PWM_PHASE21;
unsigned long * pwm_duty1=(unsigned long *)PWM_DUTY11;
unsigned long * pwm_duty2=(unsigned long *)PWM_DUTY21;

* pwm_en=enable;
* pwm_period=period;
* pwm_phase1=phase1;
* pwm_phase2=phase2;
* pwm_duty1=duty1;
* pwm_duty2=duty2;

}

int a = 1;

volatile static char key = 0;

unsigned int nirq_isr_context;
void nIRQ_Initial(void);//记得在main中initial
void isr_function(void);//记得声明在前面...

void nIRQ_Initial(void)
{

//todo: set up interrupt function
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(KEY_BASE,3);//3 = 1 | 2,表示1和2输入时都有反应

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x1);//这句话是清空中断状态

alt_ic_isr_register( 0, 1,isr_function, 0, 0 );//声明中断函数

}
void isr_function(void)
{

a = !a;
//这句话是用来测试是否进入中断的...
printf("cs - %d\n",a);
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x1);
}

int main()
{

nIRQ_Initial();//注意初始化!!!!!!!!!

unsigned int i, j;
unsigned long phase1=0x000, phase2=0x000, phase3=0x000, phase4=0x000;
unsigned long duty1=0x0000, duty2=0x0000, duty3=0x0000, duty4=0x0000;
unsigned long period=0x186A,enable=0x3;

//初始化,马达不会跑
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);

while(1)
{

if(a)//小车的普通状态,倒着跑
{
phase1=0x000, phase2=0x000, phase3=0x000, phase4=0x000;
duty1=0x1000, duty2=0x0000, duty3=0x1000, duty4=0x0000;
period=0x186A,enable=0x3;
}
else//按键后改变的状态,正向跑
{
phase1=0x000, phase2=0x000, phase3=0x000, phase4=0x000;
duty1=0x0000, duty2=0x1000, duty3=0x0000, duty4=0x1000;
period=0x186A,enable=0x3;
}
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
for(i=0;i<2550;i++);//这里一个莫名的delay...或许数据可以改小一点..
//for(j=0;j<2550;j++);//delay
}

return 0;
}

今天真的挺迷的…check电路时候一拔USB之后小车断电,

测了几次后FPGA漏电然后各种重新烧重新测..似乎就像搭这个博客一样…

反正码农嘛..写烂了debug后丢掉就好.

超声波模块

这次实验选用了GPIO1的一些管脚,注意是与GPIO0的方向相反

VCC和地线采用JP2 的11 和12口,提供4V电压(觉得这里可以优化成3.3V)

RX口和TK口对应NIOSCAR.qsf line355~line365行的引脚对应,分别对应模块的TK和RX

1
2
3
4
5
6
7
8
9
10
11
#-------------------------------------------------------------
#reuse above pins for New Ultrasound 0
#-------------------------------------------------------------
#set_location_assignment PIN_F13 -to GPIO_1[0]
#set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO_1[0]
#set_location_assignment PIN_T15 -to GPIO_1[1]
#set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO_1[1]
set_location_assignment PIN_F13 -to New_Ultrasound0_rx
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to New_Ultrasound0_rx
set_location_assignment PIN_T15 -to New_Ultrasound0_tx
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to New_Ultrasound0_tx

然后这次实验有三个task,分别是对光敏,距离和时间的检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//standard C library
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h> //like int16_t;
#include <stdbool.h>

//else
#include "io.h"
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include <altera_avalon_performance_counter.h>

//what?
#include "sys/alt_irq.h"
#include "alt_types.h"

typedef signed char char_8;
typedef unsigned char uchar_8;
typedef signed short short_16;
typedef unsigned short ushort_16;
typedef signed long long_32;
typedef unsigned long ulong_32;
typedef long long long_64;
typedef unsigned long long ulong_64;

//中断
int a = 1;

volatile static char key = 0;

unsigned int nirq_isr_context;
void nIRQ_Initial(void);//记得在main中initial
void isr_function(void);//记得声明在前面...

void nIRQ_Initial(void)
{

//todo: set up interrupt function
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(KEY_BASE,3);//3 = 1 | 2,表示1和2输入时都有反应

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x1);//这句话是清空中断状态

alt_ic_isr_register( 0, 1,isr_function, 0, 0 );//声明中断函数

}
void isr_function(void)
{

a = !a;
//这句话是用来测试是否进入中断的...
printf("cs - %d\n",a);
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x1);
}
//操作函数,Address是传入地址,x是对应命令
unsigned int light(long Address,long x)
{

unsigned int i;
unsigned char res_l, res_h;
Uart_send_byte(Address, 0xe8);
for (i = 0; i < 2000; i++)
;
Uart_send_byte(Address, 0x02);
for (i = 0; i < 2000; i++)
;
Uart_send_byte(Address,x);//修改的函数..
res_h = Uart_receive_byte(Address);
for (i = 0; i < 1000; i++);
res_l = Uart_receive_byte(Address);

return (((unsigned int) res_h) << 8) + res_l;
}


#define task3 //这里改成123分别测试

int main()
{

printf("HELLO WORLD\n");
nIRQ_Initial();
while(1){
ultrasound_init(NEW_ULTRASOUND0_BASE);//重置测位函数
#ifdef task2
int cnt = 0,i;
for(i = 0;i <5;i++)
{
cnt += ultrasound_read(NEW_ULTRASOUND0_BASE, a);//a = 0, 5m; a = 1, 11m;
}//消除噪音
cnt /= 5;
printf("%d.%dm\n",cnt/1000,cnt%1000);
#endif

#ifdef task1
printf("%d\n",light(NEW_ULTRASOUND0_BASE,0xa0) );
#endif

#ifdef task3
int clk = light(NEW_ULTRASOUND0_BASE,0x1e)*170 ;
printf("%d.%dm\n", clk / 1000000 , clk % 1000000);
//相对来说,这个测距更为精确,但是探测很多次之后似乎会死机???
#endif
}
return 0;
}

light函数传入x小结

传入参数 对应效果
0xa0 光敏传感器(1ms探测耗时)
0x1e 3m,返回测量时间
x from 0x01 to 0x2f (63 ~ 93) ~ 577 * x µs
0xb0 0xb2 5m,33ms,返回mm 返回µs
0xb8 0xba 11m,68ms,返回mm 返回µs
0xc4 0x45 5s 1s 休眠等待

主要函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/****************************************************************************
Function:
unsigned int ultrasound_read(long Address, unsigned char settings)

Description:
// This function receives one Byte via the corresponding UART from the Address

Precondition:
Call ultrasound_init(long Address) prior to use this function

Parameters:
long Address - Address of the UART (and therefore of the Ultrasound)
unsigned char settings - defines maximum distance to measure (1: 11m; 0: 5m)

Returns:
unsigned int - distance in mm

Remarks:
Distance in meter
***************************************************************************/

另外的笔记

进一步的省电措施

如果用户希望将省电进行到底

发送 0xc1 关 LED 探测显示,以降低电流消耗。

发送0xc0 可以恢复 LED 探测显示。

配置方法非常简单,向本模块发送指令时序:“I2C 地址 + 寄存器 2 +0xc0/0xc1”即可,
发送完成后请延时至少 2 秒,以让系统自动完成配置。并开始按照新配置工作。

测距范围

同步进程

单函数同步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include <stdlib.h>
#include "includes.h"
#include "io.h"

/* Definition of Task Stacks */
#define TASK_STACKSIZE 2048
#define N_TASKS 8 //最大进程数
OS_STK taskStk[N_TASKS][TASK_STACKSIZE];//申请栈空间


void task(void * pdata)
{

int pos = (int) pdata;
while(1)
{
printf("%d",pos);//调试输出当前改变的位
IOWR(LED_BASE, 0, IORD(LED_BASE,0) ^ (1<<pos));//改变当前位的值
OSTimeDlyHMSM(0, 0, (pos + 1), 0);//每一个延迟时间,注意不能设为0.
}
}

int main(void)
{


OSInit();
int idx;
for(idx = 0;idx < N_TASKS; ++idx)
{
OSTaskCreate( task,//同步进程函数
(void*)idx,//id(传入task函数参数)
&taskStk[idx][TASK_STACKSIZE-1],//取最后一位地址
idx+1);//优先级
//成功之后返回0
}

OSStart();//不会初始化到这里
return 0;
}

双函数同步_努力异步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <stdio.h>
#include <stdlib.h>
#include "includes.h"
#include "io.h"

/* Definition of Task Stacks */
#define TASK_STACKSIZE 2048
OS_STK task1_stk[TASK_STACKSIZE];
OS_STK task2_stk[TASK_STACKSIZE];

/* Definition of Task Priorities */

#define TASK1_PRIORITY 1
#define TASK2_PRIORITY 2

const char msg1[]={89,111,117,32,115,111,108,118,101,100,32,116,104,105,115,32,116,97,115,107,33,10};
const char msg2[]={71,111,111,100,32,106,111,98,33,32,89,111,117,32,97,114,101,32,97,119,101,115,111,109,101,33,10};

void Task1(void* pdata)
{

while (1)
{
OSTimeDlyHMSM(0, 0, 7, 250);//这段时间走task2就好,其实没有设置的很精
int i;
for(i=0; i<sizeof(msg1); i++)
{
printf("%c",msg1[i]);
IOWR(LED_BASE, 0, (1 << (i & 0x7) ));//同时用亮灯展示当前输出位,顺时针
OSTimeDlyHMSM(0, 0, 0, 250);
}
}
}


void Task2(void* pdata)
{

while (1)
{
int i;
for(i=0; i<sizeof(msg2); i++)
{
printf("%c",msg2[i]);
IOWR(LED_BASE, 0, (1 << 8-(i & 0x7) ));//逆时针
OSTimeDlyHMSM(0, 0, 0, 250);
}
OSTimeDlyHMSM(0, 0, 7, 250);//这段时间走task1就好,其实没有设置的很精确.
}
}



int main(void)
{


OSInit();//初始化
//声明task
OSTaskCreate( Task1,
(void*)0,
(void *)&task1_stk[TASK_STACKSIZE-1],
TASK1_PRIORITY);


OSTaskCreate( Task2,
(void*)0,
(void *)&task2_stk[TASK_STACKSIZE-1],
TASK2_PRIORITY);
//start multitasking
OSStart();
return 0;
}

很遗憾的是最后没有完全理解另一个进程同步函数,

在尝试的过程中发现那个函数也只是起了一个延时的作用,于是放弃了调试

同步进程这种事让我想起了C++中也可以实现233于是完成的挺顺利的

最后几次看中珠的夕阳.可惜没邂逅彩霞

FINAL

task:

完成小车避障功能

PID实现小车跟踪

努力实现创新功能

相关代码及注释…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
/*
task1: 避障
task2: 包含中断的跟踪
状态一: 20cm 跟踪, 10cm 后退
状态二: 20cm 跟踪.
task3: 跟着光强的方向走
*/
#define task2

//standard C library
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h> //like int16_t;
#include <stdbool.h>

//else
#include "io.h"
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include <altera_avalon_performance_counter.h>

//what?
#include "sys/alt_irq.h"
#include "alt_types.h"

typedef signed char char_8;
typedef unsigned char uchar_8;
typedef signed short short_16;
typedef unsigned short ushort_16;
typedef signed long long_32;
typedef unsigned long ulong_32;
typedef long long long_64;
typedef unsigned long long ulong_64;

/*PWM信号输出,控制马达*/

//first mortor
#define PWM_EN PWM0_BASE
#define PWM_PERIOD PWM0_BASE+1
#define PWM_DUTY1 PWM0_BASE+2
#define PWM_DUTY2 PWM0_BASE+3
#define PWM_PHASE1 PWM0_BASE+4
#define PWM_PHASE2 PWM0_BASE+5

//仿造PWM0函数写下的PWM2宏定义以及函数
#define PWM_EN1 PWM2_BASE
#define PWM_PERIOD1 PWM2_BASE+1
#define PWM_DUTY11 PWM2_BASE+2
#define PWM_DUTY21 PWM2_BASE+3
#define PWM_PHASE11 PWM2_BASE+4
#define PWM_PHASE21 PWM2_BASE+5

void motor_setting(unsigned long phase1, unsigned long duty1,
unsigned long phase2, unsigned long duty2,
unsigned long period,unsigned long enable);

void motor_setting1(unsigned long phase1, unsigned long duty1,
unsigned long phase2, unsigned long duty2,
unsigned long period,unsigned long enable);




//中断
int a = 1;

volatile static char key = 0;

unsigned int nirq_isr_context;
void nIRQ_Initial(void);//记得在main中initial
void isr_function(void);//记得声明在前面...

void nIRQ_Initial(void)
{
//todo: set up interrupt function
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(KEY_BASE,3);//3 = 1 | 2,表示1和2输入时都有反应

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x1);//这句话是清空中断状态

alt_ic_isr_register( 0, 1,isr_function, 0, 0 );//声明中断函数

}
void isr_function(void)
{
a = !a;
//这句话是用来测试是否进入中断的...
printf("cs - %d\n",a);
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE, 0x1);
}
//超声波操作函数,Address是传入地址,x是对应命令
unsigned int light(long Address,long x)
{
unsigned int i;
unsigned char res_l, res_h;
Uart_send_byte(Address, 0xe8);
for (i = 0; i < 2000; i++)
;
Uart_send_byte(Address, 0x02);
for (i = 0; i < 2000; i++)
;
Uart_send_byte(Address,x);//修改的函数..
res_h = Uart_receive_byte(Address);
for (i = 0; i < 1000; i++);
res_l = Uart_receive_byte(Address);

return (((unsigned int) res_h) << 8) + res_l;
}

/* 马达驱动的参数
1,2是对右边马达,phase是初始相位,duty是占空比,都得/period
enable是对于两个端口的使能
*/
unsigned long phase1=0x000, phase2=0x000, phase3=0x000, phase4=0x000;
unsigned long duty1=0x0000, duty2=0x1000, duty3=0x0000, duty4=0x0000;
unsigned long period=0x186A,enable=0x3;

/*
封装四个方向函数
up和down在for循环十次后基本能前进后退..调整了一定参数
避障中left和right函数先后退一步然后前进(也是一个for(10))
跟踪中的直接左右拐就行..for(5)
*/
void up()
{
phase1=0x000, phase2=0x000, phase3=0x000, phase4=0x000;
duty1=0x0000, duty2=0x1000, duty3=0x0000, duty4=0x1000;
period=0x186A,enable=0x3;
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
usleep(8000);

}
void down()
{
phase1=0x000, phase2=0x000, phase3=0x000, phase4=0x000;
duty1=0x1000, duty2=0x0000, duty3=0x1000, duty4=0x0000;
period=0x186A,enable=0x3;
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
usleep(20000);

}
#ifdef task1
void le()
{
down();
phase1=0x000, phase2=0x000, phase3=0x000, phase4=0x000;
duty1=0x0000, duty2=0x1000, duty3=0x1000, duty4=0x0000;
period=0x186A,enable=0x3;
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
usleep(5000);

}

void ri()
{
down();
phase1=0x000, phase2=0x000, phase3=0x000, phase4=0x000;
duty1=0x1000, duty2=0x0000, duty3=0x0000, duty4=0x1000;
period=0x186A,enable=0x3;
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
usleep(5000);
}
#else
void le()
{
phase1=0x000, phase2=0x000, phase3=0x000, phase4=0x000;
duty1=0x0000, duty2=0x1000, duty3=0x1000, duty4=0x0000;
period=0x186A,enable=0x3;
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
usleep(5000);

}

void ri()
{
phase1=0x000, phase2=0x000, phase3=0x000, phase4=0x000;
duty1=0x1000, duty2=0x0000, duty3=0x0000, duty4=0x1000;
period=0x186A,enable=0x3;
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
usleep(5000);
}
#endif

//避障中查询距离是否过近
int ck(unsigned int dis)
{
//if(dis > 2900000) return 0;
if(dis < 200000) return 0;
return 1;
}
//如果已经超过范围
int ck1(int dis)
{
if(dis > 300000 && dis < 2900000) return 1;
return 0;
}
int main()
{
printf("HELLO WORLD\n");//hello world DEBUG大法好
nIRQ_Initial();//中断初始化函数
//默认马达初始化为0
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
//PID积分参数
int tot = 0,tot1 = 0;
/*
跟踪参数
第一个是最远有效距离66.6666cm
第二个是跟踪距离
第三个是后退距离
*/
int meter = 666666;
int meter02 = 200000;
int meter03 = 100000;
int p; // cycle
//pid系数
double k = 0.3 ,j = 0.05,d = 0;
//这里是先调了一个直线的PID,然后转化成有角度后改的一个参量
int clk11; //pace

while(1){

#ifdef task3 //光敏测距
ultrasound_init(NEW_ULTRASOUND0_BASE);//重置测位函数
ultrasound_init(NEW_ULTRASOUND1_BASE);//重置测位函数
ultrasound_init(NEW_ULTRASOUND2_BASE);//重置测位函数
int clk = light(NEW_ULTRASOUND0_BASE,0xa0) ;
printf("1 => %d.%dm\t", clk );
usleep(10000);
int clk1 = light(NEW_ULTRASOUND1_BASE,0xa0) ;
printf("2 => %d.%dm\t", clk1 );
usleep(10000);
int clk2 = light(NEW_ULTRASOUND2_BASE,0xa0) ;
printf("3 => %d.%dm\n", clk2 );
usleep(10000);

#define run for(p = 0;p < 5;p++)
//选取光最强的方向
if (clk1 >= clk && clk1 >= clk2)
{
clk11 = clk1;
}//don' rotate
else if(clk >= clk1 && clk >= clk2)
{
clk11 = clk;
run le();
}//left rotate
else if(clk2 >= clk && clk2 >= clk1)
{
clk11 = clk2;
run ri();
}//right rotate
//go go go
if(clk11 < 200 )//光太弱停止..参数应该适当调大的..
{
tot = tot1 = 0;
duty1=0x0000, duty2=0x0000;
duty3=0x0000, duty4=0x0000;
}
else//PID向前跑
{
printf("up\n");
d = clk11 ;
duty1=0x0000, duty2=0x1000;
duty3=0x0000, duty4=0x1000;
tot += d;
tot1 = 0;
}
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
int rtime = (int)(100 * d );//这里乘了一个d之后记得强制转换,double有毒
if(rtime <= 0) rtime = 0;//小于零有毒..这两个有可能保持后退状态
usleep(rtime);
#endif
#ifdef task21 //测试只能前进的跟踪
ultrasound_init(NEW_ULTRASOUND0_BASE);//重置测位函数
ultrasound_init(NEW_ULTRASOUND1_BASE);//重置测位函数
ultrasound_init(NEW_ULTRASOUND2_BASE);//重置测位函数
int clk = light(NEW_ULTRASOUND0_BASE,0x1e)*170 ;
printf("1 => %d.%dm\t", clk / 1000000 , clk % 1000000);
usleep(10000);
int clk1 = light(NEW_ULTRASOUND1_BASE,0x1e)*170 ;
printf("2 => %d.%dm\t", clk1 / 1000000 , clk1 % 1000000);
usleep(10000);
int clk2 = light(NEW_ULTRASOUND2_BASE,0x1e)*170 ;
printf("3 => %d.%dm\n", clk2 / 1000000 , clk2 % 1000000);
usleep(10000);

#define run for(p = 0;p < 5;p++)

if (clk1 <= clk && clk1 <= clk2)
{
clk11 = clk1;
}//don' rotate
else if(clk <= clk1 && clk <= clk2)
{
clk11 = clk;
run le();
}//left rotate
else if(clk2 <= clk && clk2 <= clk1)
{
clk11 = clk2;
run ri();
}//right rotate
//go go go
if(clk11 > meter )
{
tot = 0;
duty1=0x0000, duty2=0x0000;
duty3=0x0000, duty4=0x0000;
}
else if(clk11 > meter02)
{
printf("up\n");
d = clk11 - meter02;
duty1=0x0000, duty2=0x1000;
duty3=0x0000, duty4=0x1000;
tot += d;
tot1 = 0;
}
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
int rtime = (int)(d * k + tot * j );
if(rtime <= 0) rtime = 0;
usleep(rtime);

#endif

//get the distance
#ifdef task2 //测试跟踪
if(a)
{
ultrasound_init(NEW_ULTRASOUND0_BASE);//重置测位函数
ultrasound_init(NEW_ULTRASOUND1_BASE);//重置测位函数
ultrasound_init(NEW_ULTRASOUND2_BASE);//重置测位函数
//用前文自己写的3m内测速函数
int clk = light(NEW_ULTRASOUND0_BASE,0x1e)*170 ;
printf("1 => %d.%dm\t", clk / 1000000 , clk % 1000000);
usleep(10000);//记得usleep,因为每个测距有个时间,不然很容易死循环..
int clk1 = light(NEW_ULTRASOUND1_BASE,0x1e)*170 ;
printf("2 => %d.%dm\t", clk1 / 1000000 , clk1 % 1000000);
usleep(10000);
int clk2 = light(NEW_ULTRASOUND2_BASE,0x1e)*170 ;
printf("3 => %d.%dm\n", clk2 / 1000000 , clk2 % 1000000);
usleep(10000);

#define run for(p = 0;p < 5;p++)//啊这个只是懒得写....
//选取距离最小的方向
if (clk1 <= clk && clk1 <= clk2)
{
clk11 = clk1;
}//don' rotate
else if(clk <= clk1 && clk <= clk2)
{
clk11 = clk;
run le();
}//left rotate
else if(clk2 <= clk && clk2 <= clk1)
{
clk11 = clk2;
run ri();
}//right rotate
//go go go
if(clk11 > meter || tot1)//保证只后退一步....(这个是一开始一直后退的修复)
{
tot = tot1 = 0;
duty1=0x0000, duty2=0x0000;
duty3=0x0000, duty4=0x0000;
}
else if( clk11 < meter03)//后退
{
printf("down\n");
d = meter03 - clk11;
duty1=0x1000, duty2=0x0000;
duty3=0x1000, duty4=0x0000;
tot1 += d;
tot = 0;

}
else if(clk11 > meter02)//前进,PID中P,I记录
{
printf("up\n");
d = clk11 - meter02;
duty1=0x0000, duty2=0x1000;
duty3=0x0000, duty4=0x1000;
tot += d;
tot1 = 0;
}
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
int rtime = (int)(d * k + (tot + tot1) * j );//同上
if(rtime <= 0) rtime = 0;
usleep(rtime);
}
else
{//只能前进,相对好控制一些
ultrasound_init(NEW_ULTRASOUND0_BASE);//重置测位函数
ultrasound_init(NEW_ULTRASOUND1_BASE);//重置测位函数
ultrasound_init(NEW_ULTRASOUND2_BASE);//重置测位函数
int clk = light(NEW_ULTRASOUND0_BASE,0x1e)*170 ;
printf("1 => %d.%dm\t", clk / 1000000 , clk % 1000000);
usleep(10000);
int clk1 = light(NEW_ULTRASOUND1_BASE,0x1e)*170 ;
printf("2 => %d.%dm\t", clk1 / 1000000 , clk1 % 1000000);
usleep(10000);
int clk2 = light(NEW_ULTRASOUND2_BASE,0x1e)*170 ;
printf("3 => %d.%dm\n", clk2 / 1000000 , clk2 % 1000000);
usleep(10000);

#define run for(p = 0;p < 5;p++)

if (clk1 <= clk && clk1 <= clk2)
{
clk11 = clk1;
}//don' rotate
else if(clk <= clk1 && clk <= clk2)
{
clk11 = clk;
run le();
}//left rotate
else if(clk2 <= clk && clk2 <= clk1)
{
clk11 = clk2;
run ri();
}//right rotate
//go go go
if(clk11 > meter )
{
tot = 0;
duty1=0x0000, duty2=0x0000;
duty3=0x0000, duty4=0x0000;
}
else if(clk11 > meter02)
{
printf("up\n");
d = clk11 - meter02;
duty1=0x0000, duty2=0x1000;
duty3=0x0000, duty4=0x1000;
tot += d;
tot1 = 0;
}
motor_setting(phase1,duty1,phase2,duty2,period,enable);
motor_setting1(phase3,duty3,phase4,duty4,period,enable);
int rtime = (int)(d * k + tot * j );
if(rtime <= 0) rtime = 0;
usleep(rtime);
}

#endif

#ifdef task1 // hide somethingelse
#define run for(p = 0;p < 10;p++)
ultrasound_init(NEW_ULTRASOUND0_BASE);//重置测位函数
ultrasound_init(NEW_ULTRASOUND1_BASE);//重置测位函数
ultrasound_init(NEW_ULTRASOUND2_BASE);//重置测位函数
int clk = light(NEW_ULTRASOUND0_BASE,0x1e)*170 ;
printf("1 => %d.%dm\t", clk / 1000000 , clk % 1000000);
usleep(10000);
int clk1 = light(NEW_ULTRASOUND1_BASE,0x1e)*170 ;
printf("2 => %d.%dm\t", clk1 / 1000000 , clk1 % 1000000);
usleep(10000);
int clk2 = light(NEW_ULTRASOUND2_BASE,0x1e)*170 ;
printf("3 => %d.%dm\n", clk2 / 1000000 , clk2 % 1000000);
usleep(10000);

//暴力枚举大法好= =(可惜忘了拍xiaoyi的列表...)
//每次做一件事就行..因为循环过来可以继续下一个任务.
if(ck(clk) && ck(clk1) && ck(clk2) )
{
run up();
}
else if(ck(clk) && ck(clk1) && !ck(clk2))
{
run le();
}
else if(ck(clk) && !ck(clk1) && ck(clk2))
{
run down();
run ri();
}
else if(ck(clk) && !ck(clk1) && !ck(clk2))
{
run le();
}
else if(!ck(clk) && !ck(clk1) && !ck(clk2))
{
run down();
}
else if(!ck(clk) && !ck(clk1) && ck(clk2))
{
run ri();
}
else if(!ck(clk) && ck(clk1) && !ck(clk2))
{
run down();
run ri();
}
else if(!ck(clk) && ck(clk1) && ck(clk2))
{
run ri();
}


printf("%d\t %d\t %d\t %d\n",duty1,duty2,duty3,duty4);

#endif
}
return 0;
}

void motor_setting(unsigned long phase1, unsigned long duty1,
unsigned long phase2, unsigned long duty2,
unsigned long period,unsigned long enable)
{
unsigned long * pwm_en= (unsigned long *)PWM_EN;
unsigned long * pwm_period=(unsigned long *)PWM_PERIOD;
unsigned long * pwm_phase1=(unsigned long *)PWM_PHASE1;
unsigned long * pwm_phase2=(unsigned long *)PWM_PHASE2;
unsigned long * pwm_duty1=(unsigned long *)PWM_DUTY1;
unsigned long * pwm_duty2=(unsigned long *)PWM_DUTY2;

* pwm_en=enable;
* pwm_period=period;
* pwm_phase1=phase1;
* pwm_phase2=phase2;
* pwm_duty1=duty1;
* pwm_duty2=duty2;
}


void motor_setting1(unsigned long phase1, unsigned long duty1,
unsigned long phase2, unsigned long duty2,
unsigned long period,unsigned long enable)
{
unsigned long * pwm_en= (unsigned long *)PWM_EN1;
unsigned long * pwm_period=(unsigned long *)PWM_PERIOD1;
unsigned long * pwm_phase1=(unsigned long *)PWM_PHASE11;
unsigned long * pwm_phase2=(unsigned long *)PWM_PHASE21;
unsigned long * pwm_duty1=(unsigned long *)PWM_DUTY11;
unsigned long * pwm_duty2=(unsigned long *)PWM_DUTY21;

* pwm_en=enable;
* pwm_period=period;
* pwm_phase1=phase1;
* pwm_phase2=phase2;
* pwm_duty1=duty1;
* pwm_duty2=duty2;

}

文章目录
  1. 1. Finding
    1. 1.1. disappear
    2. 1.2. learn C
    3. 1.3. FPGA
    4. 1.4. Teachers
    5. 1.5. else1
    6. 1.6. else2
  2. 2. 预备工作
    1. 2.1. 头文件
  3. 3. 基本IO
  4. 4. 中断
  5. 5. 计时模块
    1. 5.1. perf_get_total_time
    2. 5.2. subTask Volatilevariables
    3. 5.3. subTask 存储位置
  6. 6. 读入电压
    1. 6.1. SUBTASK 测量实际电压数值
  7. 7. PWM
    1. 7.1. 硬件实现
    2. 7.2. 软件实现
    3. 7.3. RUN THE CAR
  8. 8. 超声波模块
    1. 8.1. light函数传入x小结
    2. 8.2. 主要函数
    3. 8.3. 另外的笔记
      1. 8.3.1. 进一步的省电措施
      2. 8.3.2. 测距范围
  9. 9. 同步进程
    1. 9.1. 单函数同步
    2. 9.2. 双函数同步_努力异步
  10. 10. FINAL